home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / COMMUNIC / 1572B.ZIP / KMT_IBM4.ZIP / MSXIBM.ASM < prev    next >
Assembly Source File  |  1989-07-11  |  176KB  |  3,596 lines

  1. ; File MSXIBM.ASM
  2. ; Kermit system dependent module for IBM-PC
  3. ; Edit History
  4. ; Last edit 21 Jan 1989
  5. ; 21 Jan 1989 Avoid initializing a port until the port is accessed for regular
  6. ;  use, baud rate setting, or modem status. portin=-1 means unaccessed.
  7. ; 2 Dec 1988 Preserve UART parity etc bits in Line Control Reg.
  8. ; 30 Nov 1988 Add SET TERM CLEAR screen clear command (uses byte VTCLEAR).
  9. ; 26 Nov 1988 Add SET TERM TAB SET/CLEAR AT start-col:spacing notation.
  10. ; 21 Nov 1988 Version 2.32
  11. ; 25 Oct 1988 Add Ungermann Bass network board status check in proc chkub,
  12. ;  thanks to Fritz Buetikofer and Rene Rehmann in Switzerland.
  13. ; 9 Oct 1988 Add byte vtemu.vtchset to hold choices for VT102 emulator
  14. ;  character sets (US, UK, or Alternate-ROM). Tnx to Baruch Cochavy. The value
  15. ;  of vtemu.vtchset must match definitions in emulator file mszibm.asm.
  16. ; 5 Oct 1988 Add SET TERMINAL DIRECTION command and status display line.
  17. ; 21 August 1988 Move tests for NUL and DEL received chars to prtchr routine
  18. ;  for uniform application of tests.
  19. ; 28 July 1988 Add more UB details from Henrik Levkowetz. Double check serial
  20. ;  port address for 02f8h with COM1, for PCjr, and shift to COM2 addresses.
  21. ; 16 July 1988 Use null interrupt routine, nulint, when resetting serial port
  22. ;  because setting OUT2 low generates stray ints on some UARTs. [jrd]
  23. ; 1 July 1988 Version 2.31
  24. ; 12 June 1988 Add small changes to handle network session failures, and
  25. ;  add carry set if serini fails to init port.
  26. ; 29 May 1988 Add Ungermann Bass NetOne NETCI support from Henrik Levkowetz
  27. ;  [ohl]. Revise same to test for actual network presence and to avoid
  28. ;  interference with NetBios operations. Use "SET PORT UB-Net1"
  29. ; 23 May 1988 Hangup now resets serial port so can be re-inited with DTR high
  30. ; 21 May 1988 Tweak serrst to allow stray interrupts while resetting UART,
  31. ;  clear outstanding network requests when changing ports.
  32. ; 6 May 1988 Introduce xmtbufx for explict network double buffering of
  33. ;   xmitted data.
  34. ; 28 April 1988 fix set port bios register problem.
  35. ; 18 April 1988 Network: do another READ when char count < low water mark.
  36. ;  If BIOSn is selected skip test of Bios 40:0h for port presence.
  37. ; 3 April 1988 Ignore NUL and DEL at serial port unless DEBUG or TRANSLATE
  38. ;  INPUT are active, but pass DEL if Tek mode is active. Replace netdone
  39. ;  with new lclexit global word to shut net when Kermit exits.
  40. ; 22 March 1988 Add global byte Tekgraf which forces graphics board type
  41. ;   0=auto-sensing, 1=cga, 2=ega, 3=VGA, 5=Hercules, 5=ATT. Tekgraf stored
  42. ;   and set in this file by Set Term Graphics <board type>. [jrd]
  43. ; 6 March 1988 Ignore received XOFF's if we have already sent one. [jrd]
  44. ; 27 Feb 1988 Add global routine getmodem to return modem status in al. [jrd]
  45. ; 9 Feb 1988 Automaticallly find Interrupt ReQuest level for a port.
  46. ;   No Modem Status for network. [jrd]
  47. ; 25 Jan 1988 Revise outchr waiting on XON to use 4 millisec increments. [jrd]
  48. ; 1 Jan 1988 version 2.30
  49. ; 24 Dec 1987 Revise selection of COM1 to use COM1 name but COM2 addresses
  50. ;  if base address of 02f8 (COM2) is found in 40:00h and display notice.
  51. ;  Restore state of IRQ interrupt line when finished with serial port. [jrd]
  52. ; 31 Oct 1987 Add terminal type Tek4010, with Tek submode Tekflg. [jrd]
  53. ; 24 Oct 1987 Enhance clrbuf to empty any intermediate (net) buffers. [jrd]
  54. ; 19 Oct 1987 Fix stray tab-set at column 32. [jrd]
  55. ; 2 Oct 1987 Add PCjr baud rate table, from Ted Medin. [jrd]
  56. ; 6 Sept 1987 Allow serial port serint to send xoff when buffer fills even
  57. ;  though user may have sent xoff by hand. [jrd]
  58. ; 27 Aug 1987 Skip timeout test in OUTCHR if receive timeout is zero. [jrd]
  59. ; 23 August 1987 Add vtemu.vtflgop to hold runtime terminal settings so that
  60. ;  a reset command restores them to the Setup values, vtemu.vtflgst. Show
  61. ;  displays the vtemu.vtflgop operational values. [jrd]
  62. ; 17 August 1987 Make timing adjustments for Token Passing and single buffered
  63. ;  network adapter boards. Byte netdbfr indicates presence of double buffering;
  64. ;  it is set in chknet as a vendor option. To test your boards force dbl buf
  65. ;  then look for missing 256 byte parts of long packets sent out; missing parts
  66. ;  mean new material overwrote not-yet-sent old == single buffering. [jrd]
  67. ; 8 August 1987 Add interrupt chaining in serint. [jrd]
  68. ; 23 July 1987 Clear xofsnt and xofrcv xon/xoff flags in ihost(s/r). [jrd]
  69. ; 9 July 1987 Cure confusion about COM1/2 for IBM PCjr (address of regular
  70. ;  COM2 in 40:0h slot for COM1) with info from John Neufeld. [jrd]
  71. ; 2 July 1987 Route NetBios cancels through separate scb for systems, such
  72. ;  as Novell NetWare, which object to having active scbs touched. [jrd]
  73. ; 25 June 1987 Add trapping of Int 14H (Bios RS232 procedure) to allow
  74. ;  CTTY command to function without too much inteference from DOS. [jrd]
  75. ; 17 June 1987 Enlarge tab setting to full 132 columns at all times. [jrd]
  76. ; 11 June 1987 Add Set Term Roll on/off to control auto roll back of screen
  77. ;  when new characters are displayed; default is off (no unwinding). [jrd]
  78. ; 20 May 1987 Remove rejection of NULL and DEL chars, let callers do it. [jrd]
  79. ; 16 May 1987 Add distinction between user typed and receiver threshold
  80. ;  controlled sending of XOFF. User level overrides buffer control.[jrd]
  81. ;  Add COM3 and COM4 support: examine memory 40:00h->40:07h for selected
  82. ;  port COM1..4, resp. If word is null then set flags.comflg to 0 to say
  83. ;  undefined port. Otherwise, use that word in seg 40h as base of UART i/o
  84. ;  ports. Assume IRQ4 for COM1 and COM3 (same except for port addresses)
  85. ;  and IRQ4 for  COM2 and COM4 (again, same except for port addresses).
  86. ;  Serial port info sturcture (not values) assumed identical for all ports.
  87. ; 25 April 1987 Add Netbios compatible local area network support. [jrd]
  88. ;  Set Port command expanded to syntax SET PORT NET nodename. Use nodename
  89. ;  if acting as a client to named remote node, leave blank if running in
  90. ;  Server mode. Byte 'ttyact' is controlled by msster.asm to indicate Connect
  91. ;  mode is being used. Byte 'netdone' (stored in mssker.asm) holds offset of
  92. ;  network hangup procedure 'netclose' to be done when leaving Kermit. Hangup
  93. ;  command extended to to network hangup as well. Network uses IBM Netbios
  94. ;  standard calls (Int 5Ch) and allows for extensions of AT&T STARLAN for
  95. ;  longer node names via Int 2Bh (the later is tested before use). Virtual
  96. ;  circuits are employed. The Redirector is not necessary. Kermit can operate
  97. ;  as either a terminal (does a CALL at Connect mode startup), a file receiver
  98. ;  (does a CALL at startup), or a Kermit server (does an anonomous LISTEN at
  99. ;  startup, hence no nodename). Clients should Set Timer Off.
  100. ; Note -
  101. ; When the Bios is used for serial port i/o the modem signals DSR and CTS
  102. ; must be asserted low before the Bios will access the hardware. Jumpers
  103. ; from pin 20 (DTR) to pin 6 (DSR) and from pin 4 (RTS) to pin 5 (CTS)
  104. ; will probably be necessary.
  105. ;       From Glenn Everhart (who suggested using the Bios alternative)
  106. ;
  107.         public  serini, serrst, clrbuf, outchr, coms, vts, vtstat
  108.         public  dodel, ctlu, cmblnk, locate, prtchr, dobaud, clearl
  109.         public  dodisk, getbaud, beep, termtb, shomodem, getmodem, mdmhand
  110.         public  count, xofsnt, puthlp, putmod, clrmod, poscur, holdscr
  111.         public  sendbr, sendbl, machnam, setktab, setkhlp, lclini, showkey
  112.         public  ihosts, ihostr, dtrlow, serhng, comptab, pcwait
  113.         include mssdef.h
  114.  
  115. off     equ     0
  116. bufon   equ     1               ; buffer level xon/xoff on-state control flag
  117. usron   equ     2               ; user level xon/xoff on-state control flag
  118.  
  119. mntrgh  equ     bufsiz*3/4      ; High point = 3/4 of buffer full
  120. mntrgl  equ     bufsiz/4        ; Low point = 1/4 buffer full
  121.  
  122. BRKBIT  EQU     040H            ; Send-break bit.
  123. TIMERCMD EQU    43h             ; 8253/4 Timer chip command port
  124. TIMER2DATA EQU  42h             ; 8253/4 Timer 2 data port
  125. PPI_PORT EQU    61h             ; 8255 prog peripheral chip control port
  126. MCONF   EQU     11H             ; Bios Machine configuration s/ware interrupt.
  127. KEYB    EQU     16H             ; Bios keyboard software interrupt
  128. VIDEO   EQU     10H             ; Bios Video display software interrupt
  129. RS232   EQU     14H             ; Bios RS232 serial port s/ware interrupt
  130.  
  131. ; constants used by serial port handler
  132. ;;MDMDAT1       EQU     03F8H           ; Address of port com1 (data)
  133. ;;MDMCOM1       EQU     03FBH           ; Address of port com1 (command)
  134. ;;MDMSTS1       EQU     03FDH           ; Address of port com1 (status)
  135. ;;MDMDAT2       EQU     02F8H           ; Port com2 data
  136. ;;MDMCOM2       EQU     02FBH           ; Port com2 command
  137. ;;MDMSTS2       EQU     02FDH           ; Port com2 status
  138. MDMINTV EQU     0CH             ; IRQ4 com1/3 port interrupt vector
  139. MDINTV2 EQU     0BH             ; IRQ3 com2/4 port interrupt vector
  140. MDMINTO EQU     0EFH            ; Mask to enable interrupt level IRQ4
  141. MDINTO2 EQU     0F7H            ; Mask to enable interrupt level IRQ3
  142. MDMINTC EQU     010H            ; Bit to set to disable interrupts for IRQ4
  143. MDINTC2 EQU     008H            ; Bit to set to disable interrupts for IRQ3
  144. EOICOM  EQU     0064H           ; End of interrupt for IRQ4
  145. EOICOM2 EQU     0063H           ; End of interrupt for IRQ3
  146.  
  147. INTCONT EQU     0021H           ; Address of 8259 interrupt controller ICW2-3
  148. INTCON1 EQU     0020H           ; Address of 8259 ICW1
  149. MDMINP  EQU     1               ; Input ready bit
  150. MDMOVER EQU     2               ; Receiver overrun
  151.  
  152. ; external variables used:
  153. ; drives - # of disk drives on system
  154. ; flags - global flags as per flginfo structure defined in pcdefs
  155. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  156. ; portval - pointer to current portinfo structure (currently either port1
  157. ;    or port2)
  158. ; port1, port2 - portinfo structures for the corresponding ports
  159. ; low_rgt - low byte = last column (typ 79), high byte = last text row
  160. ;  (typ 23) in screen coordinates (start at 0), set by msyibm.
  161.  
  162. ; global variables defined in this module:
  163. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  164. ; setktab - keyword table for redefining keys (should contain a 0 if
  165. ;    not implemented)
  166. ; setkhlp - help for setktab.
  167.  
  168. datas   segment public 'datas'
  169.         extrn   drives:byte, flags:byte, trans:byte, ttyact:byte
  170.         extrn   portval:word, port1:byte, port2:byte, port3:byte, port4:byte
  171.         extrn   lclexit:word, rxtable:byte, decbuf:byte, taklev:byte
  172.         extrn   refresh:byte, scbattr:byte, low_rgt:word, vtemu:byte
  173.         extrn   vtroll:byte, tekflg:byte, tekgraf:byte, vtclear:byte
  174.  
  175. ; structure for status information table sttab.
  176. stent   struc
  177. sttyp   dw      ?               ; type (actually routine to call)
  178. msg     dw      ?               ; message to print
  179. val2    dw      ?               ; needed value: another message, or tbl addr
  180. tstcel  dw      ?               ; address of cell to test, in data segment
  181. basval  dw      0               ; base value, if non-zero
  182. stent   ends
  183.  
  184. setktab db      0               ; superceded by msuibm code, return 0 here
  185. setkhlp db      '$'             ; and add empty help string
  186. holdscr db      0               ; Hold-Screen, non-zero to stop reading
  187. savsci  dd      ?               ; old serial port interrupt vector
  188. sav232  dd      ?               ; Original Bios Int 14H address, in Code seg
  189. savirq  db      ?               ; Original Interrupt mask for IRQ
  190. savlcr  db      ?               ; Original Line Control Reg (3fbh) contents
  191. brkval  db      BRKBIT          ; What to send for a break
  192. brkadr  dw      0               ; Where to send it
  193. intkind db      0               ; cause of serial port interrupt
  194. isps2   db      0               ; non-zero if real IBM PS/2
  195. modem   mdminfo <>
  196. hngmsg  db      cr,lf,' The phone or network connection should have hungup'
  197.         db      cr,lf,'$'
  198. hnghlp  db      cr,lf,' The modem control lines DTR and RTS for the current'
  199.         db      ' port are forced low (off)'
  200.         db      cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  201.         db      ' high (on) when it exits.',cr,lf
  202.         db      ' For networks, the active session is terminated.',cr,lf,'$'
  203. erms40  db      cr,lf,'?Warning: Unrecognized baud rate',cr,lf,'$'
  204. erms41  db      cr,lf,'?More parameters are needed$'
  205. badbd   db      cr,lf,'Unimplemented baud rate$'
  206. badprt  db      cr,lf,' Serial port $'
  207. badprt2 db      ' is not available',cr,lf,'$'
  208. biospt  db      'BIOS$'
  209. compt   db      'COM$'
  210. unkpt   db      'Unknown$'
  211. biosmsg db      cr,lf,'This port operates through the Bios',cr,lf,'$'
  212. msmsg1  db      cr,lf,'  Modem is not ready: DSR is off$'
  213. msmsg2  db      cr,lf,'  Modem is ready:     DSR is on$'
  214. msmsg3  db      cr,lf,'  no Carrier Detect:  CD  is off$'
  215. msmsg4  db      cr,lf,'  Carrier Detect:     CD  is on$'
  216. msmsg5  db      cr,lf,'  no Clear To Send:   CTS is off$'
  217. msmsg6  db      cr,lf,'  Clear To Send:      CTS is on$'
  218. msmsg7  db      cr,lf,'  Modem is not used by the Network$'
  219.  
  220. machnam db      'IBM-PC$'
  221. crlf    db      cr,lf,'$'
  222. delstr  db      BS,BS,'  ',BS,BS,'$'    ; Delete string
  223. clrlin  db      cr,'$'                  ; Clear line (just the cr part)
  224. tabmsg  db      'Tab stops ''T'' and columns -$'
  225. clone   db      0               ; clone flag (0 = real, 'B' = system Bios,
  226.                                 ; 'N'=NetBios/network, 'U'=Ungermann/Bass net)
  227. portin  db      -1              ; Has comm port been initialized, -1=not used
  228. xofsnt  db      0               ; Say if we sent an XOFF
  229. xofrcv  db      0               ; Say if we received an XOFF
  230. parmsk  db      0ffh            ; parity mask, 0ffh for no parity, 07fh with
  231. flowoff db      0               ; flow-off char, Xoff or null (if no flow)
  232. flowon  db      0               ; flow-on char, Xon or null
  233. pcwcnt  dw      240             ; number of loops for 1 millisec in pcwait
  234. temp    dw      0
  235. temp2   dw      0
  236. tempsci dw      0               ; temp storage for serint
  237. tempdum dw      0               ; temp storage for serdum
  238. rdbuf   db      80 dup (?)      ; temporary storage
  239.  
  240.                                         ; begin Terminal emulator data set
  241. termtb  db      tttypes                 ; entries for Status, not Set
  242.         mkeyw   'Heath-19',ttheath
  243.         mkeyw   'none',ttgenrc
  244.         mkeyw   'Tek4010',tttek
  245.         mkeyw   'VT102',ttvt100
  246.         mkeyw   'VT52',ttvt52
  247.  
  248. vttbl   db      18                      ; number of entries
  249.         mkeyw   'Character-set',chaval+300h
  250.         mkeyw   'Clear-screen',1000h    ; 1000h = marker here
  251.         mkeyw   'Color',200H            ; screen fore/back colors; 200H=marker
  252.         mkeyw   'Cursor-style',curval
  253.         mkeyw   'Direction',dirval
  254.         mkeyw   'Graphics',800h         ; Tek graphics board, 800h=marker
  255.         mkeyw   'Heath-19',ttheath+100H ; note 100H flag for decoding here
  256.         mkeyw   'Keyclick',keyval
  257.         mkeyw   'Margin-bell',marval
  258.         mkeyw   'None',ttgenrc+100H
  259.         mkeyw   'Newline',newval
  260.         mkeyw   'Rollback',400h         ; note 400H flag for decoding
  261.         mkeyw   'Screen-background',scrval
  262.         mkeyw   'Tabstops',tabval
  263.         mkeyw   'Tek4010',tttek+100H
  264.         mkeyw   'VT102',ttvt100+100H
  265.         mkeyw   'VT52',ttvt52+100H
  266.         mkeyw   'Wrap',wraval
  267.  
  268. scrtab  db      02H                     ; screen attributes
  269.         mkeyw   'normal',00H
  270.         mkeyw   'reverse',01H
  271.  
  272. dirtab  db      2                       ; writing direction
  273.         mkeyw   'left-to-right',0
  274.         mkeyw   'right-to-left',1
  275.  
  276. curtab  db      02H                     ; cursor attributes
  277.         mkeyw   'block',00H
  278.         mkeyw   'underline',01H
  279.  
  280. chatab  db      3                       ; character set (pound sign choice)
  281.         mkeyw   'UK-ascii',0
  282.         mkeyw   'US-ascii',1            ; US ASCII is default (1)
  283.         mkeyw   'Alternate-ROM',3       ; Alternate-ROM character set
  284.  
  285. graftab db      6
  286.         mkeyw   'auto-sensing',0        ; autosensing
  287.         mkeyw   'CGA',1
  288.         mkeyw   'EGA',2
  289.         mkeyw   'VGA',3
  290.         mkeyw   'Hercules',4
  291.         mkeyw   'ATT',5
  292.  
  293. tabtab  db      02H                     ; label says it all!
  294.         mkeyw   'at',0FFH               ; For setting tab stops
  295.         mkeyw   'Clear',00H             ; For clearing tab stops
  296.  
  297. alltab  db      02H                     ; more tab command decoding
  298.         mkeyw   'all',00H
  299.         mkeyw   'at',01H
  300.  
  301. vtable  dw      ontab, curtab, chatab, ontab, ontab, ontab, scrtab, dirtab,0
  302.  
  303. vtsflg equ      this byte               ; define small digits xxxval
  304. newval  equ     $-vtsflg                ; and mask for bit in byte
  305.         db      vsnewline
  306. curval  equ     $-vtsflg
  307.         db      vscursor
  308. chaval  equ     $-vtsflg
  309.         db      vsshift3
  310. keyval  equ     $-vtsflg
  311.         db      vskeyclick
  312. wraval  equ     $-vtsflg
  313.         db      vswrap
  314. marval  equ     $-vtsflg
  315.         db      vsmarginbell
  316. scrval  equ     $-vtsflg
  317.         db      vsscreen
  318. dirval  equ     $-vtsflg
  319.         db      vswdir
  320. numflgs equ     $-vtsflg
  321. tabval  equ     $-vtsflg
  322.         db      0
  323. vtrtns  dw      numflgs dup (flgset), tabset ; dispatch table for vtsflg
  324. colortb db      0,4,2,6,1,5,3,7         ; color reversed-bit setting bytes
  325. clrset  db      ?                       ; Temp for SET Term Tabstops xxx
  326.  
  327. vthlp   db      ' one of the following:',cr,lf
  328.       db '  terminal types of:  None, Heath-19, VT52, VT102, or Tek4010',cr,lf
  329.         db '  Newline-mode    Cursor-style        Character-set (US, UK, Alt)'
  330.         db      cr,lf
  331.         db '  Keyclick        Margin-bell         Screen-background'
  332.         db      ' (normal, reverse)',cr,lf
  333.         db '  Tabstops        Wrap (long lines)   Color (fore & background)'
  334.         db      cr,lf,'  Clear-screen  (clears old startup screen)'
  335.         db      cr,lf,'  Direction Left-to-right or Right-to-left'
  336.         db      ' (screen writing direction)'
  337.         db      cr,lf,'  Graphics  (type of display adapter when in Tek4010'
  338.         db      ' mode)'
  339.         db      cr,lf,'  Rollback  (undo screen roll back before writing new'
  340.         db      ' chars, default=off)$'
  341. clrhlp  db      ' one of the following:'
  342.         db      cr,lf,'  AT #s  (to set tabs at column #s)    or'
  343.         db      ' AT start-column:spacing'
  344.         db      cr,lf,'  Clear AT #s (clears individual tabs) or'
  345.         db      ' AT start-column:spacing'
  346.         db      cr,lf,'  Clear ALL  (to clear all tabstops)'
  347.         db      cr,lf,'  Ex: Set term tab at 10, 20, 34        sets tabs'
  348.         db      cr,lf,'  Ex: Set term tab at 1:8        sets tabs at 1, 9,'
  349.                 db      ' 17,...$'
  350.         db      cr,lf,'  Ex: Set term tab clear at 9, 17, 65   clears tabs'
  351.         db      cr,lf,'  Ex: Set term tab clear at 1:8  clears tabs at 1, 9,'
  352.                 db      ' 17,...$'
  353. tbserr  db      cr,lf,'?Column number is not in range 1 to screen width-1$'
  354. colhlp  db      cr,lf,'  Set Term Color  value, value, value, ...'
  355.         db      cr,lf,'   0 no-snow mode on an IBM CGA and white on black'
  356.         db      cr,lf,'   1 for high intensity foreground'
  357.         db      cr,lf,'  10 for fast CGA screen updating (may cause snow)'
  358.         db      cr,lf,'  Foreground color (30-37) = 30 + sum of colors'
  359.         db      cr,lf,'  Background color (40-47) = 40 + sum of colors'
  360.         db      cr,lf,'    where colors are  1 = red, 2 = green, 4 = blue'
  361.         db      cr,lf,'  Ex: 0, 1, 37, 44   IBM CGA(0), bright(1) white(37)'
  362.         db      ' chars on a blue(44) field'
  363.         db      cr,lf,'  Attributes are applied in order of appearance.$'
  364. colerr  db      cr,lf,'?Value not in range of 0, 1, 10, 30-37, or 40-47$'
  365. vtwrap  db      'Term wrap-lines: $'
  366. vtbell  db      'Term margin-bell: $'
  367. vtnewln db      'Term newline: $'
  368. vtcur   db      'Term cursor-style: $'
  369. vtcset  db      'Term character-set: $'
  370. vtclik  db      'Term key-click: $'
  371. vtscrn  db      'Term screen-background: $'
  372. colst1  db      'Term color  foreground:3$'
  373. colst2  db      ' background:4$'
  374. vtgraf  db      'Term graphics: $'
  375. vtrolst db      'Term rollback: $'
  376. vtdir   db      'Term direction: $'
  377.                                                         ; terminal emulator
  378. vtstbl  stent   <srchkb,vtwrap,ontab,vswrap,vtemu.vtflgop>      ; line wrap
  379.         stent   <srchkb,vtbell,ontab,vsmarginbell,vtemu.vtflgop>; margin bell
  380.         stent   <srchkb,vtcur,curtab,vscursor,vtemu.vtflgop>    ; cursor type
  381.         stent   <srchkb,vtnewln,ontab,vsnewline,vtemu.vtflgop>  ; newline
  382.         stent   <srchkb,vtscrn,scrtab,vsscreen,vtemu.vtflgop>   ; screen
  383.         stent   <srchkw,vtcset,chatab,vtemu.vtchset>            ; char set
  384.         stent   <srchkb,vtdir,dirtab,vswdir,vtemu.vtflgop>      ; write direct
  385.         stent   <colstat>                                       ; VT100 colors
  386.         stent   <srchkb,vtclik,ontab,vskeyclick,vtemu.vtflgop>  ; keyclick
  387.         stent   <srchkw,vtrolst,ontab,vtroll>
  388.         stent   <srchkw,vtgraf,graftab,tekgraf>
  389.         stent   <filler>
  390.         stent   <tabstat>       ; VT100 tab status - needs one whole line
  391.         dw      0               ; end of table
  392.                                                 ; end of Terminal data set
  393.  
  394. ontab   db      2                       ; Two entries
  395.         mkeyw   'off',0
  396.         mkeyw   'on',1
  397.  
  398. comptab db      15                      ; communications port options
  399.         mkeyw   'Bios1','0'+1           ; '0' is to flag value as forced Bios
  400.         mkeyw   'Bios2','0'+2
  401.         mkeyw   'Bios3','0'+3
  402.         mkeyw   'Bios4','0'+4
  403.         mkeyw   'COM1',1                ; these go straight to the hardware
  404.         mkeyw   'COM2',2
  405.         mkeyw   'COM3',3
  406.         mkeyw   'COM4',4
  407.         mkeyw   '1',1                   ; straight to the hardware
  408.         mkeyw   '2',2
  409.         mkeyw   '3',3
  410.         mkeyw   '4',4
  411.         mkeyw   'NetBios','N'           ; Netbios
  412.         mkeyw   'UB-Net1','U'           ; Ungermann Bass Net One
  413.         mkeyw   '   ',0                 ; port is not present, for Status
  414.  
  415. ; this table is indexed by the baud rate definitions given in
  416. ; pcdefs.  Unsupported baud rates should contain FF.
  417. bddat   label   word
  418.         dw      9E4H            ; 45.5 baud
  419.         dw      900H            ; 50 baud
  420.         dw      600H            ; 75 baud
  421.         dw      417H            ; 110 baud
  422.         dw      359H            ; 134.5 baud
  423.         dw      300H            ; 150 baud
  424.         dw      180H            ; 300 baud
  425.         dw      0C0H            ; 600 baud
  426.         dw      60H             ; 1200 baud
  427.         dw      40H             ; 1800 baud
  428.         dw      3AH             ; 2000 baud
  429.         dw      30H             ; 2400 baud
  430.         dw      18H             ; 4800 baud
  431.         dw      0CH             ; 9600 baud
  432.         dw      06H             ; 19200 baud
  433.         dw      03H             ; 38400 baud
  434.         dw      02h             ; 57600 baud
  435.         dw      01h             ; 115200 baud
  436. baudlen equ     ($-bddat)/2     ; number of entries above
  437.  
  438. jrbddat label   word            ; Baud rate table for IBM PCjrs [tm]
  439.         dw      0FFH            ; 45.5 baud  -- Not supported
  440.         dw      8bfH            ; 50 baud
  441.         dw      5d3H            ; 75 baud
  442.         dw      3f9H            ; 110 baud
  443.         dw      340H            ; 134.5 baud
  444.         dw      2e9H            ; 150 baud
  445.         dw      175H            ; 300 baud
  446.         dw      0baH            ; 600 baud
  447.         dw      5dH             ; 1200 baud
  448.         dw      3eH             ; 1800 baud
  449.         dw      38H             ; 2000 baud
  450.         dw      2fH             ; 2400 baud
  451.         dw      18H             ; 4800 baud
  452.         dw      0CH             ; 9600 baud
  453.         dw      06H             ; 19200 baud
  454.         dw      03H             ; 38400 baud
  455.         dw      02h             ; 57600 baud
  456.         dw      01h             ; 115200 baud
  457.  
  458. ; this table is indexed by the baud rate definitions given in
  459. ; pcdefs.  Unsupported baud rates should contain FF.
  460. ; Clone: bits are for Bios speed, no parity, 8 data bits. [jrd]
  461. clbddat   label   word
  462.         dw      0FFH            ; 45.5 baud  -- Not supported
  463.         dw      0FFH            ; 50 baud
  464.         dw      0FFH            ; 75 baud
  465.         dw      03H             ; 110 baud
  466.         dw      0FFH            ; 134.5 baud
  467.         dw      23H             ; 150 baud
  468.         dw      43H             ; 300 baud
  469.         dw      63H             ; 600 baud
  470.         dw      83H             ; 1200 baud
  471.         dw      0ffH            ; 1800 baud
  472.         dw      0FFH            ; 2000 baud
  473.         dw      0a3H            ; 2400 baud
  474.         dw      0c3H            ; 4800 baud
  475.         dw      0e3H            ; 9600 baud
  476.         dw      0FFH            ; 19200 baud
  477.         dw      0FFH            ; 38400 baud
  478.         dw      0FFH            ; 57600 baud
  479.         dw      0FFH            ; 115200 baud
  480. ; variables for serial interrupt handler
  481.  
  482. source  db      bufsiz+2 DUP(?) ; Buffer for data from port (+ 2 guard bytes)
  483. srcpnt  dw      source          ; Pointer in buffer (DI)
  484. count   dw      0               ; Number of chars in int buffer
  485. mst     dw      0               ; Modem status address
  486. mdat    dw      0               ; Modem data address
  487. mdeoi   db      0               ; End-of-Interrupt value
  488. mdmhand db      0               ; Modem status register, current
  489.  
  490. ; Information structures for IBM Netbios compatible Local Area Networks
  491.                                 ; network constants
  492. netint  equ     5ch             ; Netbios interrupt
  493. nadd    equ     30h             ; Add name
  494. ncall   equ     10h             ; CALL, open a virtual circuit session
  495. ncancel equ     35h             ; Cancel command in scb buffer
  496. ndelete equ     31h             ; Delete Name
  497. nhangup equ     12h             ; Hangup virtual circuit session
  498. nlisten equ     11h             ; Listen for session caller
  499. naustat equ     33h             ; Network Adapter Unit, get status of
  500. nreceive equ    15h             ; Receive on virtual circuit
  501. nreset  equ     32h             ; Reset NAU and tables
  502. nsend   equ     14h             ; Send on virtual circuit
  503. nsestat equ     34h             ; Session, get status of
  504. netbrk  equ     70h             ; STARLAN Int 5bh send Break
  505. nowait  equ     80h             ; no-wait, command modifier
  506. npending equ    0ffh            ; Pending request
  507. exnbios equ     0400h           ; Int 2ah exec netbios call, error retry
  508. nbuflen equ     256             ; bytes in each network buffer (two of them)
  509. netbios equ     8000h           ; network type bit, using NetBios
  510. starlan equ     1               ; network type bit, AT&T STARLAN
  511. netone  equ     02h             ; [ohl] type bit, Ungermann-Bass Net/One
  512. ;xncall equ     74h             ; [ohl] Net/One extended call function
  513. netci   equ     6Bh             ; [ohl] Net/One command interface interrupt,
  514.                                 ; [ohl]  used for the following functions:
  515. nciwrit equ     0000h           ; [ohl] Net/One write function
  516. nciread equ     0100h           ; [ohl] Net/One read function
  517. ncistat equ     0700h           ; [ohl] Net/One status function
  518. ncicont equ     0600h           ; [ohl] Net/One control function
  519. ncibrk  equ     02h             ; [ohl] Net/One code for a break
  520. ncidis  equ     04h             ; [ohl] Net/One code for disconnect
  521. ncihld  equ     06h             ; [ohl] code for placing a connection on hold
  522. ;; pcnet values:        0       no network available at all
  523. ;;                      1       network board reports itself as present
  524. ;;                      2       and session is in progress
  525. ;; extrn byte pcnet is  defined in msster.
  526.  
  527. portn   prtinfo <0FFFH,0,defpar,1,0,defhand,floxon> ; port struc for PORTN
  528. scbst struc                     ; Session (Network) Control Block [PCnet comp]
  529.         scb_cmd         db 0    ; command code for Netbios Int 5ch
  530.         scb_err         db 0    ; error return or request is pending
  531.         scb_vcid        db 0    ; virtual circuit ident number
  532.         scb_num         db 0    ; local name-number
  533.         scb_baddr       dw ?    ; buffer address, offset
  534.                         dw datas ;  and segment
  535.         scb_length      dw ?    ; length of buffer data
  536.         scb_rname       db '*               ' ; remote name, 16 chars space
  537.         scb_lname       db 'mskermit        ' ; local name      filled
  538.                         db 0    ; reserved
  539.                         db 0    ; reserved
  540.         scb_post        dw ?    ; interrupt driven post address, offset
  541.                         dw code ;  and segment
  542.                         db 0    ; LAN_num (adapter #), set to zero for STARLAN
  543.         scb_done        db 0    ; command complete status
  544.                                 ; the 14 bytes below are normally 'reserved'
  545.                                 ; STARLAN uses 5 for long/special call names
  546.                                 ;  together with STARLAN specific Int 5bh
  547.         scb_vrname      dw 0,0  ; Variable length call name ptr offset,segment
  548.         scb_vrlen       db 0    ; length of vrname
  549.                         db 9 dup (0)    ; reserved
  550. scbst   ends
  551.  
  552. rcv     scbst   <,,,,rcvbuf,,length rcvbuf,,,,,rpost>; declare scb for rcvr
  553. xmt     scbst   <,,,,xmtbuf,,length xmtbuf,,,,,spost>;  for xmtr
  554. lsn     scbst   <,,,,xmtbuf,,length xmtbuf,,,,,lpost>;  for server listen
  555. can     scbst   <>                                   ;  for cancels
  556. pcnet   db      0               ; Network is functioning
  557. xmtbuf  db      nbuflen dup (0) ; network buffer for transmitter
  558. xmtcnt  dw      0               ; occupancy in current output buffer
  559. xmtbufx db      nbuflen dup (0) ; external version of xmtbuf (dbl buffers)
  560. rcvbuf  db      nbuflen dup (0) ; network buffer for receiver
  561. nambuf  db      65 dup (?)      ; network long name storage (STARLAN)
  562. sposted db      0               ; send interlock, 0 if no send posted
  563. rposted db      0               ; rcv interlock, 0 if no receive posted
  564. lposted db      0               ; listen outstanding (if non-zero)
  565. netdbfr db      0               ; non-zero if net board is double buffered
  566. deflname db     'mskermit        ' ; default local name, 16 bytes
  567. nsbrk   dw      0               ; net can send Break
  568. nettype dw      0               ; kind of local area net (vendor bit field)
  569. chkmsg1 db      cr,lf,' Cannot construct a local Kermit name, error = $'
  570. chkmsg2 db      cr,lf,lf,' Name $'
  571. chkmsg3 db      ' is already in use. Please enter another of'
  572.         db      cr,lf,' 1 - 14 letters or numbers (or nothing to quit): $'
  573. netmsg1 db      cr,lf,' Checking if our node name is unique ...$'
  574. netmsg2 db      cr,lf,' The network is active, our name is $'
  575. nonetmsg db     cr,lf,'?The network is not available$'
  576. nethlp  db      cr,lf,' Enter node name of remote system,'
  577.         db      cr,lf,'  or a carriage return to use current name,'
  578.         db      cr,lf,'  or a carriage return for server mode.$'
  579. ngodset db      cr,lf,' Connecting to network node: $'
  580. nbadset db      bell,cr,lf,' Cannot reach network node: $'
  581. recmsg  db      cr,lf,' Network receive failed, status = $'
  582. sndmsg  db      cr,lf,' Network send failed, status = $'
  583. naskpmt db      cr,lf,' A network session is active.',cr,lf
  584.         db      ' Enter RESUME to resume it or NEW to start a new session.'
  585.         db      cr,lf,'> $'
  586. nettab  db      2
  587.         mkeyw   'New',0
  588.         mkeyw   'Resume',1
  589. datas   ends
  590.  
  591. code    segment public 'code'
  592.         extrn   comnd:near, dopar:near, defkey:near, lclyini:near
  593.         extrn   sleep:near, atsclr:near, scrseg:near,scrloc:near, scrsync:near
  594.         extrn   atoi:near, strlen:near, prtscr:near, scroff:near, scron:near
  595.         extrn   srchkb:near, srchkw:near, prompt:near, statc:near
  596.         assume  cs:code, ds:datas
  597.  
  598. ; local initialization
  599.  
  600. lclini  proc    near
  601.         mov     flags.comflg,1  ; assume COM1 for communications port
  602. ;;;     call    coms2           ; setup serial port modem.info for COM1
  603.         call    model           ; get model of IBM machine
  604.         call    lclyini         ; let other modules initialize too...
  605.         ret
  606. lclini  endp
  607.  
  608. ; this is called by Kermit initialization.  It checks the
  609. ; number of disks on the system, sets the drives variable
  610. ; appropriately.  Returns normally.
  611.  
  612. DODISK  PROC    NEAR
  613.         int     mconf                   ; Get equipment configuration
  614.         mov     ah,al                   ; Store AL value for a bit
  615.         and     al,01H                  ; First, look at bit 0
  616.         jz      dodsk0                  ; No disk drives -- forget it
  617.         mov     al,ah                   ; Get back original value
  618.         mov     cl,6                    ; Shift over bits 6 and 7
  619.         shr     al,cl                   ; To positions 0 and 1
  620.         inc     al                      ; Want 1 thru 4 (not 0 thru 3)
  621. dodsk0: mov     drives,al               ; Remember how many.
  622.         ret
  623. DODISK  ENDP
  624.  
  625. ; The IBM PC's. If jr then redo IBM baud rate with jr's values. [jrd]
  626. model   proc    near
  627.         mov     isps2,0                 ; PS/2 present indicator
  628.         push    es
  629.         push    ax                      ; get IBM model code at F000:FFFEh
  630.         mov     ax,0f000h               ; address ROM
  631.         mov     es,ax
  632.         mov     al,byte ptr es:[0fffeh] ; get model id byte
  633.         cmp     al,0fdh                 ; PC jr?
  634.         jne     modelx                  ; ne = no
  635.         push    ds
  636.         pop     es                      ; set es to datas segment
  637.         mov     si,offset bddat         ; regular IBM baud rate table
  638.         mov     di,offset jrbddat       ; PCjr baud rate table
  639.         mov     cl,baudlen              ; number of words to copy
  640.         mov     ch,0
  641.         cld
  642.         rep     movsw                   ; copy PCjr values to IBM table
  643.         jmp     short modelx
  644. model2: mov     ah,0ch                  ; AT and PS/2 configuration call
  645.         mov     al,0
  646.         int     15h                     ; IBM Bios
  647.         jc      modelx                  ; c = no information
  648.         cmp     word ptr es:[bx+2],040fch ; PS/2 model 50?
  649.         je      model3                  ; e = yes
  650.         cmp     word ptr es:[bx+2],050fch ; PS/2 model 60?
  651.         je      model3                  ; e = yes
  652.         cmp     byte ptr es:[bx+2],0f8h ; PS/2 model 80?
  653.         jne     modelx                  ; ne = no
  654. model3: mov     isps2,1                 ; say real PS/2 for IRQ setting
  655. modelx: pop     ax
  656.         pop     es
  657.         ret
  658. model   endp
  659.  
  660. ; show the definition of a key.  The terminal argument block (which contains
  661. ; the address and length of the definition tables) is passed in ax.
  662. ; Returns a string to print in AX, length of same in CX.
  663. ; Returns normally. Obsolete, name here for external reference only.
  664. showkey proc    near
  665.         ret                             ; return
  666. showkey endp
  667.  
  668. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  669. ; Uses byte mdmhand, the modem line status register. [jrd]
  670. shomodem proc   near
  671.         mov     ah,cmcfm                ; get a confirm
  672.         call    comnd
  673.          jmp    r                       ; no confirm
  674.          nop
  675.         mov     dx,offset msmsg7        ; no modem status for network
  676.         call    getmodem                ; get modem status
  677.         mov     mdmhand,al
  678.         mov     ah,prstr
  679.         mov     dx,offset msmsg1        ; modem ready msg
  680.         test    mdmhand,20h             ; is DSR asserted?
  681.         jz      shomd1                  ; z = no
  682.         mov     dx,offset msmsg2        ; say not asserted
  683. shomd1: int     dos
  684.         mov     dx,offset msmsg3        ; CD asserted msg
  685.         test    mdmhand,80h             ; CD asserted?
  686.         jz      shomd2                  ; z = no
  687.         mov     dx,offset msmsg4        ; say not asserted
  688. shomd2: int     dos
  689.         mov     dx,offset msmsg5        ; CTS asserted msg
  690.         test    mdmhand,10h             ; CTS asserted?
  691.         jz      shomd3                  ; z = no
  692.         mov     dx,offset msmsg6        ; say not asserted
  693. shomd3: mov     ah,prstr
  694.         int     dos
  695.         jmp     rskp
  696. shomodem endp
  697.  
  698. ; Get modem status and set global byte mdmhand. Preserve all registers.
  699. getmodem proc   near                    ; gets modem status upon request
  700.         cmp     portin,-1               ; done any port yet?
  701.         jne     getmod1                 ; ne = yes
  702.         mov     bl,flags.comflg         ; pass current port ident
  703.         call    comstrt                 ; do SET PORT command now
  704.          ret                            ; failed to set port
  705.          nop
  706.          nop
  707. getmod1:mov     al,0                    ; assume nothing is on
  708.         cmp     clone,'N'               ; Network?
  709.         je      getmodx                 ; e = yes, no status
  710.         cmp     clone,'B'               ; Bios?
  711.         je      getmod2                 ; e = yes
  712.         cmp     flags.comflg,0          ; null port?
  713.         je      getmodx                 ; e = yes, no status
  714.         mov     dx,mst                  ; hardware
  715.         inc     dx                      ; uart status reg
  716.         in      al,dx
  717.         jmp     short getmodx
  718. getmod2:mov     ah,3                    ; ask Bios for modem status into al
  719.         push    dx
  720.         mov     dl,flags.comflg         ; get port id
  721.         cmp     dl,'0'                  ; ascii?
  722.         jb      getmod3                 ; b = no
  723.         sub     dl,'0'                  ; remove ascii bias
  724. getmod3:int     rs232
  725.         pop     dx
  726. getmodx:mov     ah,0                    ; return status in al
  727.         ret
  728. getmodem endp
  729.  
  730. ; Clear the input buffer. This throws away all the characters in the
  731. ; serial interrupt buffer.  This is particularly important when
  732. ; talking to servers, since NAKs can accumulate in the buffer.
  733. ; Returns normally.
  734.  
  735. CLRBUF  PROC    NEAR
  736.         cli
  737.         mov     srcpnt,offset source    ; receive circular buffer
  738.         mov     count,0                 ; receive circular buffer
  739.         sti
  740.         call    prtchr                  ; empty any intermediate (net) buffers
  741.          nop                            ; got a char, clear again
  742.          nop
  743.          nop
  744.         cli
  745.         mov     srcpnt,offset source    ; receive circular buffer
  746.         mov     count,0                 ; receive circular buffer
  747.         mov     xmtcnt,0                ; network output buffer count
  748.         sti
  749.         ret
  750. CLRBUF  ENDP
  751.  
  752. ; Clear to the end of the current line.  Returns normally.
  753. ; Upgraded for Topview compatibility. [jrd]
  754. CLEARL  PROC    NEAR
  755.         push    ax
  756.         push    bx
  757.         push    dx
  758.         mov     ah,3                    ; Clear to end of line
  759.         mov     bh,0
  760.         int     video                   ; Get current cursor position into dx
  761.         mov     ax,dx                   ; Topview compatible clear line
  762.         mov     bh,ah                   ; same row
  763.         mov     bl,byte ptr low_rgt     ; last column
  764.         call    atsclr                  ; clear from ax to bx, screen coord
  765.         pop     dx
  766.         pop     bx
  767.         pop     ax
  768.         ret
  769. CLEARL  ENDP
  770.  
  771. ; This routine blanks the screen.  Returns normally.
  772. ; Upgraded to Topview compatiblity. [jrd]
  773. CMBLNK  PROC    NEAR
  774.         push    ax
  775.         push    bx
  776.         xor     ax,ax                   ; from screen loc 0,0
  777.         mov     bx,low_rgt      ; to end of text screen (lower right corner)
  778.         inc     bh                      ; include status line
  779.         call    atsclr               ; do Topview compatible clear, in msyibm
  780.         pop     bx
  781.         pop     ax
  782.         ret
  783. CMBLNK  ENDP
  784.  
  785. ; Locate: homes the cursor.  Returns normally.
  786.  
  787. LOCATE  PROC    NEAR
  788.         mov dx,0                        ; Go to top left corner of screen
  789.         jmp poscur
  790. LOCATE  ENDP
  791.  
  792. ; Position the cursor according to contents of DX:
  793. ; DH contains row, DL contains column.  Returns normally.
  794. POSCUR  PROC    NEAR
  795.         push    ax
  796.         push    bx
  797.         mov     ah,2                    ; Position cursor
  798.         mov     bh,0                    ; page 0
  799.         int     video
  800.         pop     bx
  801.         pop     ax
  802.         ret
  803. POSCUR  ENDP
  804.  
  805. ; Delete a character from the terminal.  This works by printing
  806. ; backspaces and spaces.  Returns normally.
  807.  
  808. DODEL   PROC    NEAR
  809.         mov     ah,prstr
  810.         mov     dx,offset delstr        ; Erase weird character
  811.         int     dos
  812.         ret
  813. DODEL   ENDP
  814.  
  815. ; Move the cursor to the left margin, then clear to end of line.
  816. ; Returns normally.
  817.  
  818. CTLU    PROC    NEAR
  819.         mov     ah,prstr
  820.         mov     dx,offset clrlin
  821.         int     dos
  822.         call    clearl
  823.         ret
  824. CTLU    ENDP
  825.  
  826.  
  827. BEEP    PROC    NEAR
  828.         push    ax
  829.         push    cx
  830.         mov     al,10110110B    ; Gen a short beep (long one losses data.)
  831.         out     timercmd,al     ; set Timer to to mode 3
  832.         mov     ax,1512         ; divisor, for frequency
  833.         out     timer2data,al   ; send low byte first
  834.         mov     al,ah
  835.         out     timer2data,al
  836.         in      al,ppi_port     ; get 8255 Port B setting
  837.         or      al,3            ; turn on speaker and timer
  838.         out     ppi_port,al     ; start speaker and timer
  839.         push    ax
  840.         mov     ax,40           ; 40 millisecond beep, calibrated time
  841.         call    pcwait
  842.         pop     ax
  843.         in      al,ppi_port
  844.         and     al,0fch         ; turn off speaker and timer
  845.         out     ppi_port,al
  846.         pop     cx
  847.         pop     ax
  848.         ret
  849. BEEP    ENDP
  850.  
  851. ; write a line in inverse video at the bottom of the screen...
  852. ; the line is passed in dx, terminated by a $.  Returns normally.
  853. putmod  proc    near
  854.         push    ax              ; save regs
  855.         push    bx
  856.         push    cx
  857.         push    dx              ; preserve message
  858.         mov     bl,scbattr      ; screen attributes at Kermit init time
  859.         and     bl,77h          ; get colors, omit bright and blink
  860.         rol     bl,1            ; interchange fore and background
  861.         rol     bl,1
  862.         rol     bl,1
  863.         rol     bl,1
  864.         mov     bh,0            ; preset page 0
  865.         mov     temp,bx         ; temp = page 0, reverse video
  866.         mov     dx,low_rgt      ; ending location is lower right corner
  867.         inc     dh              ;  of status line
  868.         mov     cx,dx           ; start is status left side
  869.         xor     cl,cl           ; left side
  870.         mov     ax,600h         ; scroll to clear the line
  871.         mov     bh,byte ptr temp ; set inverse video attributes
  872.         int     video
  873.         mov     dx,low_rgt      ; last text line
  874.         inc     dh              ; status line
  875.         xor     dl,dl           ; left side
  876.         call    poscur
  877.         pop     si              ; get message back
  878.         mov     cx,1            ; only one char at a time
  879.         xor     bh,bh           ; page 0
  880.         cld
  881. putmo1: lodsb                   ; get a byte
  882.         cmp     al,'$'          ; end of string?
  883.         je      putmo2
  884.         push    si              ; save si
  885.         push    ax              ; and the char
  886.         call    poscur
  887.         inc     dl              ; increment for next write
  888.         pop     ax              ; recover char
  889.         mov     ah,9            ; try this
  890.         mov     bx,temp         ; page 0, inverse video
  891.         int     video
  892.         pop     si              ; recover pointer
  893.         jmp     putmo1
  894. putmo2: pop     cx
  895.         pop     bx
  896.         pop     ax
  897.         ret
  898. putmod  endp
  899.  
  900. ; clear the mode line written by putmod.  Returns normally.
  901. clrmod  proc    near
  902.         push    ax              ; save regs
  903.         push    bx
  904.         push    cx
  905.         push    dx
  906.         mov     ax,600h         ; do a scroll up
  907.         mov     dx,low_rgt      ; ending location is lower right corner
  908.         inc     dh              ;  of status line
  909.         mov     cx,dx           ; start is status left side
  910.         xor     cl,cl           ; left side
  911.         mov     bh,scbattr      ; use screen attributes at Kermit init time
  912.         int     video
  913.         pop     dx
  914.         pop     cx
  915.         pop     bx
  916.         pop     ax
  917.         ret
  918. clrmod  endp
  919.  
  920. ; put a help message on the screen.  This one uses reverse video...
  921. ; pass the message in ax, terminated by a null.  Returns normally.
  922. puthlp  proc    near
  923.         push    bx              ; save regs
  924.         push    cx
  925.         push    dx
  926.         push    si
  927.         push    ax              ; preserve this
  928.         cld
  929.         mov     bl,scbattr      ; screen attributes at Kermit init time
  930.         and     bl,77h          ; get colors, omit bright and blink
  931.         rol     bl,1            ; interchange fore and background
  932.         rol     bl,1
  933.         rol     bl,1
  934.         rol     bl,1
  935.         mov     bh,0            ; preset page 0
  936.         mov     temp,bx         ; temp = page 0, reverse video
  937.  
  938.         mov     si,ax           ; point to it
  939.         mov     dh,1            ; init counter
  940. puthl1: lodsb                   ; get a byte
  941.         cmp     al,lf           ; linefeed?
  942.         jne     puthl2          ; no, keep going
  943.         inc     dh              ; count it
  944.         jmp     puthl1          ; and keep looping
  945. puthl2: cmp     al,0            ; end of string?
  946.         jne     puthl1          ; no, keep going
  947.         mov     ax,600h         ; scroll to clear window
  948.         xor     cx,cx           ; from top left
  949.         mov     dl,4fh          ; to bottom right of needed piece
  950.         mov     bh,70h          ; inverse video
  951.         mov     bh,bl           ; inverse video
  952.         int     video
  953.         call    locate          ; home cursor
  954.         mov     bx,0070h        ; bh = page 0, bl = inverse video
  955.         mov     bx,temp
  956.         mov     cx,1            ; one char at a time
  957.         cld                     ; scan direction is forward
  958.         pop     si              ; point to string again
  959. puthl3: lodsb                   ; get a byte
  960.         cmp     al,0            ; end of string?
  961.         je      puthl4          ; yes, stop
  962.         push    si              ; save around bios call
  963.         cmp     al,' '          ; printable?
  964.         jb      puth21          ; b = no
  965.         mov     ah,9            ; write char at current cursor position
  966.         int     video           ; do the Bios int 10h call
  967.         inc     dl              ; point to next column
  968.         jmp     puth23          ; move cursor there
  969. puth21: cmp     al,cr           ; carriage return?
  970.         jne     puth22          ; ne = no
  971.         xor     dl,dl           ; set to column zero
  972.         jmp     puth23
  973. puth22: cmp     al,lf           ; line feed?
  974.         jne     puth23
  975.         inc     dh              ; go to next line
  976. puth23: mov     ah,2            ; set cursor position to dx
  977.         int     video
  978.         pop     si              ; restore pointer
  979.         jmp     puthl3          ; and keep going
  980. puthl4: mov     dh,byte ptr low_rgt+1   ; go to last line
  981.         inc     dh
  982.         xor     dl,dl
  983.         call    poscur          ; position cursor
  984.         pop     si
  985.         pop     dx
  986.         pop     cx
  987.         pop     bx
  988.         ret
  989. puthlp  endp
  990.                                         ; begin Terminal set & status code
  991.  
  992. ; SET Term parameters, especially for use with VT100 emulator. [jrd]
  993. ; Taken from work done originally by James Harvey IUPUI.
  994. ; VTS is called only by mssset to set terminal type and characteristics.
  995. ; Enter via direct jmp. Exit rskp for success, ret for failure.
  996. VTS     proc    near                    ; SET TERM whatever
  997.         mov     ah,cmkey                ; Parse another keyword
  998.         mov     bx,offset vthlp         ; Use this help
  999.         mov     dx,offset vttbl         ; Use this table
  1000.         call    comnd
  1001.          jmp    r
  1002.          nop
  1003.         cmp     bh,1H                   ; marker for terminal type?
  1004.         je      vsetu0                  ; e = yes
  1005.         cmp     bh,2h                   ; marker for set term color?
  1006.         jne     vset1                   ; ne = no
  1007.         jmp     vsetu2                  ; e = yes
  1008. vset1:  cmp     bh,3h                   ; marker for character set?
  1009.         je      vsetu3                  ; e = yes
  1010.         cmp     bh,4h                   ; marker for roll back control?
  1011.         je      vsetu4                  ; e = yes
  1012.         cmp     bh,10h                  ; marker for clear-screen?
  1013.         jne     vset1a                  ; ne = no
  1014.         mov     ah,cmcfm                ; yes
  1015.         call    comnd
  1016.          jmp    r
  1017.          nop
  1018.         mov     vtclear,1               ; set trigger for emulator startup
  1019.         jmp     rskp                    ; return successfully
  1020.  
  1021. vset1a: cmp     bh,8h                   ; marker for graphics type?
  1022.         jne     short vsetu1            ; ne = no, dispatch on bl
  1023.         jmp     vsetu8                  ; yes
  1024.  
  1025. vsetu0: mov     temp,bx                 ; set terminal type
  1026.         mov     ah,cmcfm
  1027.         call    comnd                   ; Get a confirm
  1028.          jmp    r                       ; Didn't get a confirm
  1029.          nop
  1030.         mov     bx,temp
  1031.         mov     flags.vtflg,bl          ; Set the terminal emulation type
  1032.         mov     tekflg,0                ; clear Tek sub mode
  1033.         jmp     rskp
  1034.  
  1035. vsetu1: mov     bh,0                    ; remove marker bits in bh
  1036.         shl     bx,1                    ; Make bx a word index
  1037.         jmp     vtrtns[bx]              ; Dispatch
  1038.  
  1039. vsetu3: mov     ah,cmkey                ; Set Term character set
  1040.         mov     bx,0                    ; Use character set table for help
  1041.         mov     dx,offset chatab        ; Use character set table
  1042.         call    comnd
  1043.          jmp    r                       ; failure
  1044.          nop
  1045.         mov     temp,bx
  1046.         mov     ah,cmcfm                ; get a confirm
  1047.         call    comnd
  1048.          jmp    vsetu0                  ; did not get a confirm
  1049.          nop
  1050.         mov     ax,temp                 ; recover value
  1051.         mov     vtemu.vtchset,al        ; set default character set
  1052.         jmp     rskp                    ; return successfully
  1053.  
  1054. vsetu4: mov     ah,cmkey                ; Set Term Roll On/Off, auto roll back
  1055.         mov     bx,0                    ; Use on/off table as help
  1056.         mov     dx,offset ontab         ; Use on/off table
  1057.         call    comnd
  1058.          jmp    r                       ; bad keyword
  1059.          nop
  1060.         mov     temp,bx
  1061.         mov     ah,cmcfm                ; get a confirm
  1062.         call    comnd
  1063.          jmp    r                       ; did not get a confirm
  1064.          nop
  1065.         mov     bx,temp
  1066.         mov     vtroll,bl               ; set roll state (0=no auto rollback)
  1067.         jmp     rskp                    ; return successfully
  1068.  
  1069.                                      ; Set Term Color foreground, background
  1070. vsetu2: mov     ah,cmtxt                ; get number(s) after set term color
  1071.         mov     dx,offset colhlp        ; use this help
  1072.         mov     bx,offset rdbuf         ; temp buffer
  1073.         mov     rdbuf,0                 ; clear the buffer
  1074.         call    comnd
  1075.          jmp    r
  1076.          nop
  1077.         cmp     ah,0                    ; text given?
  1078.         jne     vsetu2a                 ; ne = yes
  1079.         mov     ah,prstr
  1080.         mov     dx,offset erms41        ; say need more parameters
  1081.         int     dos
  1082.         jmp     rskp
  1083. vsetu2a:mov     bx,vtemu.att_ptr        ; get address of attributes byte
  1084.         mov     bl,[bx]                 ; get attributes
  1085.         mov     byte ptr temp,bl        ; save in work temp
  1086.         mov     si,offset rdbuf         ; si = place where atoi wants text
  1087.         jmp     vsetu2b                 ; analyze
  1088.  
  1089. colbad: mov     ah,prstr                ; not in range - complain and exit
  1090.         mov     dx,offset colerr
  1091.         int     dos
  1092.         jmp     rskp
  1093.  
  1094. vsetu2x:mov     al,byte ptr temp        ; get current attributes
  1095.         mov     bx,vtemu.att_ptr        ; get address of attributes byte
  1096.         mov     [bx],al                 ; store attributes
  1097.         jmp     rskp                    ; and return normally
  1098.  
  1099. vsetu2b:mov     dx,si                   ; analyze values
  1100.         call    strlen                  ; current length of text to cx
  1101.         jcxz    vsetu2x                 ; z = nothing left
  1102. vsetu2c:cmp     byte ptr[si],' '        ; scan off leading spaces
  1103.         jne     vsetu2d                 ; ne = non-blank text found
  1104.         inc     si                      ; look at next char
  1105.         loop    vsetu2c                 ; cx characters to examine
  1106.         jcxz    vsetu2x                 ; z = nothing left
  1107. vsetu2d:mov     ah,cl                   ; put length where atoi wants it
  1108.         call    atoi                    ; convert text to numeric in ax
  1109.          jmp    colbad                  ; no value available
  1110.          nop
  1111.         cmp     ax,0                    ; reset all? regular IBM CGA refresh
  1112.         je      vsetu2j                 ; e = yes
  1113.         cmp     ax,1                    ; high intensity?
  1114.         je      vsetu2k                 ; e = yes
  1115.         cmp     ax,10                   ; fast refresh?
  1116.         je      vsetu2l                 ; e = yes
  1117.         cmp     ax,30                   ; check range
  1118.         jb      colbad                  ; b = too small. complain
  1119.         cmp     ax,37
  1120.         jna     vsetu2f                 ; 30-37 is foreground color
  1121.         cmp     ax,40
  1122.         jb      colbad
  1123.         cmp     ax,47                   ; compare as unsigned
  1124.         jna     vsetu2g                 ; 40-47 is background
  1125.         jmp     colbad                  ; else error
  1126.  
  1127. vsetu2h:inc     si                      ; skip separator
  1128.         cmp     byte ptr[si-1],0        ; ended on null?
  1129.         jne     vsetu2b                 ; ne = no, do more
  1130.         jmp     vsetu2x                 ; e = yes, exit
  1131.  
  1132. vsetu2f:sub     al,30                   ; remove foreground bias
  1133.         and     byte ptr temp,not 07H   ; clear foreground bits
  1134.         mov     bx,ax
  1135.         mov     al,colortb[bx]          ; get reversed bit pattern
  1136.         or      byte ptr temp,al        ; load new bits
  1137.         jmp     vsetu2h
  1138.  
  1139. vsetu2g:sub     al,40                   ; remove background bias
  1140.         and     byte ptr temp,not 70H   ; clear background bits
  1141.         mov     bx,ax
  1142.         mov     al,colortb[bx]          ; get reversed bit pattern
  1143.         mov     cl,4                    ; rotate 4 positions
  1144.         rol     al,cl
  1145.         or      byte ptr temp,al        ; load new bits
  1146.         jmp     vsetu2h
  1147.  
  1148. vsetu2j:mov     refresh,0               ; Regular (slow) screen refresh
  1149.         mov     byte ptr temp,07h       ; clear all, set white on black
  1150.         jmp     vsetu2h                 ; get next value
  1151. vsetu2k:or      byte ptr temp,08h       ; set high intensity
  1152.         jmp     vsetu2h                 ; get next value
  1153. vsetu2l:mov     refresh,1               ; Fast screen refresh
  1154.         jmp     vsetu2h
  1155.  
  1156. vsetu8: mov     ah,cmkey                ; Set Term graphics
  1157.         mov     bx,0                    ; Use graphics table as help
  1158.         mov     dx,offset graftab       ; Use graphics table
  1159.         call    comnd
  1160.          jmp    r                       ; bad keyword
  1161.          nop
  1162.         mov     temp,bx
  1163.         mov     ah,cmcfm                ; get a confirm
  1164.         call    comnd
  1165.          jmp    r                       ; did not get a confirm
  1166.          nop
  1167.         mov     bx,temp
  1168.         mov     tekgraf,bl              ; set Tek graphics board type
  1169.         jmp     rskp                    ; return successfully
  1170.  
  1171. ; SET Term flags. These are the (near) equivalent of VT100 Setup mode values.
  1172.  
  1173. flgset: mov     word ptr rdbuf,bx       ; save index
  1174.         mov     ah,cmkey                ; Another keyword
  1175.         mov     dx,vtable[bx]           ; The table to use
  1176.         mov     bx,0                    ; Use default help
  1177.         call    comnd
  1178.          jmp    r
  1179.          nop
  1180.         mov     temp,bx                 ; Save switch value
  1181.         mov     ah,cmcfm                ; Confirm it
  1182.         call    comnd
  1183.          jmp    r
  1184.          nop
  1185.         mov     dx,temp                 ; Restore switch value
  1186.         mov     bx,word ptr rdbuf       ; And index
  1187.         shr     bx,1                    ; Make it a byte index
  1188.         mov     al,vtsflg[bx]           ; Get the flag
  1189.         cmp     dx,0                    ; Set or clear?
  1190.         je      flgse1                  ; Go clear it
  1191.         or      vtemu.vtflgst,al        ; Set the flag
  1192.         or      vtemu.vtflgop,al        ; in runtime flags too
  1193.         jmp     rskp                    ; Give good return
  1194.  
  1195. flgse1: not     al                      ; Complement
  1196.         and     vtemu.vtflgst,al        ; Clear the indicated setup flag
  1197.         and     vtemu.vtflgop,al        ; Clear the indicated runtime flag
  1198.         jmp     rskp                    ; Give good return
  1199.  
  1200. ;       SET Term Tabstops Clear ALL
  1201. ;       SET Term Tabstops Clear AT n1, n2, ..., nx
  1202. ;       SET Term Tabstops At n1, n2, ..., nx
  1203.  
  1204. tabset: cld                             ; Make sure this is clear
  1205.         mov     di,offset decbuf        ; clear our temp work area here
  1206.         mov     cx,132                  ; 132 columns
  1207.         mov     al,0                    ; set "not touched" indicator
  1208.         rep     stosb                   ; in all decbuf slots
  1209.         mov     ah,cmkey                ; Parse keyword
  1210.         mov     bx,offset clrhlp        ; help text
  1211.         mov     dx,offset tabtab        ; table
  1212.         call    comnd
  1213.          jmp    r
  1214.          nop
  1215.         mov     clrset,2                ; code for set a tab
  1216.         cmp     bl,0                    ; Was it set or clear?
  1217.         jne     tabse1                  ; SET - go parse column number(s)
  1218.         mov     clrset,1                ; code for clear at/all tab(s)
  1219.         mov     ah,cmkey                ; CLEAR - parse ALL or AT
  1220.         mov     bx,offset clrhlp        ; Use this help text
  1221.         mov     dx,offset alltab        ; Parse ALL or AT
  1222.         call    comnd
  1223.          jmp    r
  1224.          nop
  1225.         cmp     bx,0                    ; ALL?
  1226.         jne     tabse1                  ; ne = AT, clear at specific places
  1227.         mov     ah,cmcfm                ; Confirm the ALL
  1228.         call    comnd
  1229.          jmp    r
  1230.          nop
  1231.         mov     al,1                    ; ALL, means clear all tab stops
  1232.         mov     cx,132                  ; use 132 columns
  1233.         mov     di,offset decbuf
  1234.         cld
  1235.         rep     stosb
  1236.         jmp     tabcpy                  ; update active & coldstart tabs
  1237.  
  1238. tabse1: mov     dx,offset clrhlp        ; Tell them we want a column number
  1239.         mov     ah,cmtxt                ; get text w/o white space
  1240.         mov     bx,offset rdbuf         ; temp buffer
  1241.         call    comnd
  1242.          jmp    r
  1243.          nop
  1244.         cmp     ah,0                    ; anything given?
  1245.         jne     tabse2                  ; ne = yes
  1246.         mov     ah,prstr
  1247.         mov     dx,offset erms41        ; say need more parameters
  1248.         int     dos
  1249.         jmp     rskp
  1250. tabse2: mov     si,offset rdbuf         ; si = place where atoi wants text
  1251. tabse3: mov     dx,si
  1252.         call    strlen                  ; cx = current length of text
  1253.         jcxz    tabcpy                  ; z = nothing left
  1254.         mov     ah,cl                   ; put length where atoi wants it
  1255.         call    atoi                    ; convert text to numeric in ax
  1256.          jmp    tabcpy                  ;  no number available
  1257.          nop
  1258.         mov     bx,ax                   ; for subscripting in code below
  1259.         dec     bx                      ; put column in range 0-131
  1260.         cmp     bx,0                    ; check range (1-132 --> 0-131)
  1261.         jl      tbsbad                  ; l = too small. complain
  1262.         cmp     bl,132-1                ; more than the right most column?
  1263.         jna     tabse4                  ; na = no, is ok
  1264. tbsbad: mov     ah,prstr                ; not in range - complain and exit
  1265.         mov     dx,offset tbserr
  1266.         int     dos
  1267.         jmp     rskp
  1268.  
  1269. tabse4: mov     al,clrset               ; get value for setting or clearing
  1270.         mov     decbuf[bx],al           ; store in tabs temp work array
  1271.         cmp     byte ptr [si],':'       ; start-column:spacing notation?
  1272.         jne     tabse3                  ; ne = no, get next tab stop
  1273.         inc     si                      ; skip colon, do start:space analysis
  1274.         mov     temp,bx                 ; save reg around atoi call
  1275.         mov     dx,si                   ; string address for strlen
  1276.         call    strlen                  ; get remaining string length into cx
  1277.         jcxz    tabcpy                  ; z = no space value, all done here
  1278.         mov     ah,cl                   ; ah = string length for atoi
  1279.         call    atoi                    ; get space value into ax
  1280.          jmp    tabcpy                  ;  no number available
  1281.          nop
  1282.         mov     bx,temp
  1283.         mov     cx,ax                   ; "space" value
  1284.         cmp     cx,0                    ; zero spacing?
  1285.         jne     tabse4a                 ; ne = no
  1286.         inc     cx                      ; don't get caught with zero spacing
  1287. tabse4a:mov     al,clrset               ; get tab set or clear indicator
  1288. tabse5: add     bx,cx                   ; new column value
  1289.         cmp     bx,132-1                ; largest tab stop
  1290.         ja      tabcpy                  ; a = done largest tab stop
  1291.         mov     decbuf[bx],al           ; store set or clear indicator
  1292.         jmp     short tabse5            ; finish spacing loop, then do tabcpy
  1293.  
  1294. tabcpy: mov     cx,132                  ; update all active tab stops
  1295.         mov     si,vtemu.vttbst         ; in terminal emulator's active buffer
  1296.         mov     di,vtemu.vttbs          ; and in the cold-start buffer
  1297.         mov     bx,0                    ; subscript
  1298. tabcpy1:mov     al,decbuf[bx]           ; get a table entry into al
  1299.         or      al,al                   ; what is the code?
  1300.         jz      tabcpy3                 ; z = do not touch
  1301.         cmp     al,2                    ; set a tab?
  1302.         je      tabcpy2                 ; e = set the tab
  1303.         mov     byte ptr [bx+si],0      ; clear the tab
  1304.         mov     byte ptr [bx+di],0      ; clear the tab
  1305.         jmp     short tabcpy3
  1306. tabcpy2:mov     byte ptr [bx+si],0ffh   ; set the tab
  1307.         mov     byte ptr [bx+di],0ffh   ; set the tab
  1308. tabcpy3:inc     bx                      ; inc subscript
  1309.         loop    tabcpy1
  1310.         jmp     rskp                    ; Give good return
  1311.  
  1312. VTS     endp                            ; end of Set Term things
  1313.  
  1314.               ; Terminal Status display, called within STAT0: in MSSSET
  1315. VTSTAT  proc    near                    ; enter with di within sttbuf, save bx
  1316.         push    bx
  1317.         mov     bx,offset vtstbl        ; table of things to show
  1318.         call    statc                   ; status common code, in mssset
  1319.          nop
  1320.          nop
  1321.          nop
  1322.         pop     bx
  1323.         ret                             ; return to STAT0: in MSSSET
  1324.  
  1325. colstat proc    near                    ; foreground/background color status
  1326.         push    si
  1327.         mov     si,offset colst1
  1328.         cld
  1329. colstd1:lodsb
  1330.         cmp     al,'$'                  ; end of string?
  1331.         je      colstd2                 ; e = yes
  1332.         stosb
  1333.         jmp     short colstd1
  1334. colstd2:mov     bx,vtemu.att_ptr        ; pointer to attributes byte
  1335.         mov     bl,byte ptr[bx]
  1336.         mov     bh,0
  1337.         push    bx
  1338.         and     bx,7                    ; get foreground set
  1339.         mov     al,colortb[bx]          ; get reversed bit pattern
  1340.         add     al,'0'                  ; add ascii bias
  1341.         stosb
  1342.         pop     bx
  1343.         mov     si,offset colst2
  1344. colstd3:lodsb
  1345.         cmp     al,'$'
  1346.         je      colstd4
  1347.         stosb
  1348.         jmp     short colstd3
  1349. colstd4:mov     cl,4                    ; rotate 4 positions
  1350.         shr     bl,cl
  1351.         and     bx,7                    ; get background set
  1352.         mov     al,colortb[bx]          ; get reversed bit pattern
  1353.         add     al,'0'                  ; add ascii bias
  1354.         stosb
  1355.         pop     si
  1356.         ret
  1357. colstat endp
  1358.                                         ; Tabs Status display
  1359. tabstat proc    near                    ; display tabs ruler for Status
  1360.         push    dx
  1361.         cld
  1362. tabstd2:mov     al,cr
  1363.         stosb
  1364. tabsta0:mov     si,vtemu.vttbst         ; active tabs address, not shadow
  1365.         mov     cl,byte ptr low_rgt     ; loop screen width-1 times
  1366.         xor     ch,ch                   ; clear high byte
  1367.         dec     si                      ; dec for inc below
  1368.         xor     ax,ax                   ; tens counter
  1369. tabsta1:mov     dl,'.'                  ; default position symbol
  1370.         inc     si                      ; start with position 1
  1371.         inc     al
  1372.         cmp     al,10                   ; time to roll over?
  1373.         jb      tabsta2                 ; b = not yet
  1374.         mov     al,0                    ; modulo 10
  1375.         inc     ah
  1376.         mov     dl,ah                   ; display a tens-digit
  1377.         add     dl,'0'
  1378.         cmp     dl,'9'                  ; larger than 90?
  1379.         jbe     tabsta2                 ; be = no
  1380.         sub     dl,10                   ; roll over to 0, 1, etc
  1381. tabsta2:cmp     byte ptr [si],0         ; is tab set?
  1382.         je      tabsta3                 ; e = no
  1383.         mov     dl,'T'                  ; yes, display a 'T'
  1384. tabsta3:push    ax
  1385.         mov     al,dl
  1386.         stosb
  1387.         pop     ax
  1388.         loop    tabsta1                 ; loop til done (cx has count)
  1389.         pop     dx
  1390.         ret
  1391. tabstat endp
  1392.  
  1393. filler  proc    near                    ; use space
  1394.         mov     cx,20
  1395.         mov     al,' '
  1396.         rep     stosb
  1397.         ret
  1398. filler  endp
  1399. VTSTAT  endp                            ; end of Terminal set & status code
  1400.  
  1401. ; Compute number of iterations needed in procedure pcwait inner loop
  1402. ; to do one millisecond delay increments. Uses Intel 8253/8254 timer chip
  1403. ; (timer #2) to measure elapsed time assuming 1.193182 MHz clock.
  1404. ; Called by serini below. For IBM PC compatible machines.
  1405. ; Regs preserved. 16 April 87 [jrd]
  1406. pcwtst  proc    near
  1407.         push    ax
  1408.         push    cx
  1409.         push    dx
  1410.         mov     pcwcnt,256      ; software loop, initial value
  1411.         in      al,ppi_port     ; 8255 chip port B, 61h
  1412.         and     al,0fch         ; speaker off (bit 1), stop timer (bit 0)
  1413.         out     ppi_port,al     ; do it
  1414.   ; 10 = timer 2, 11 = load low byte then high byte, 010 = mode 2, 0 = binary
  1415.         mov     al,10110100B    ; command byte
  1416.         out     timercmd,al     ; timer command port, 43h
  1417.         xor     al,al           ; clear initial count for count-down
  1418.         out     timer2data,al   ; low order byte of count preset, to port 42h
  1419.         out     timer2data,al   ; high order byte, to the same place
  1420.         in      al,ppi_port     ; get 8255 setting
  1421.         mov     dl,al           ; remember it in dl
  1422.         and     al,0fch         ; clear our control bits
  1423.         or      al,1            ; start counter now (Gate = 1, speaker is off)
  1424.         out     ppi_port,al     ; do it, OUT goes low
  1425.                                 ; this is the test loop
  1426.         mov     ax,8            ; wait 8 millisec
  1427.         call    pcwait          ; call the software timer
  1428.                                 ; end test loop
  1429.         mov     al,dl           ; restore ppi port, stop timer
  1430.         out     ppi_port,al
  1431.         in      al,timer2data   ; read count down value
  1432.         xchg    al,ah           ; save low order byte
  1433.         in      al,timer2data   ; get high order byte
  1434.         xchg    ah,al           ; put in correct sequence
  1435.         neg     ax              ; subtract from zero to get elapsed tics
  1436.         xor     dx,dx           ; clear high order divisor
  1437.         add     ax,1193/2       ; round up
  1438.         adc     dx,0            ; for very very slow machines
  1439.         mov     cx,1193         ; tics per millisec
  1440.         div     cx              ; count / 1193 yields millisecs, quo=ax
  1441.         mov     cx,ax           ; retain whole number of milliseconds
  1442.         mov     ax,pcwcnt       ; get current pcwait inner loop count
  1443.         xor     dx,dx           ; clear high order field for division
  1444.         shl     ax,1
  1445.         rcl     dx,1
  1446.         shl     ax,1
  1447.         rcl     dx,1
  1448.         shl     ax,1
  1449.         rcl     dx,1            ; dx:ax = current counter times 8 loops
  1450.         cmp     cx,0            ; no millisec? (super speed machines)
  1451.         ja      pcwtst1         ; a = some
  1452.         inc     cx              ; use at least one
  1453. pcwtst1:div     cx              ; divide by observed milliseconds
  1454.         mov     pcwcnt,ax       ; store quotient as new inner loop counter
  1455.         pop     dx
  1456.         pop     cx
  1457.         pop     ax
  1458.         ret
  1459. pcwtst  endp
  1460.  
  1461. ;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
  1462. ;; Thanks to Bernie Eiben for this one. Modified to use adjustable
  1463. ; inner loop counter (pcwcnt, adjusted by proc pcwtst) by [jrd].
  1464. pcwait  proc    near
  1465.         push    cx
  1466. pcwai0: mov     cx,pcwcnt       ; inner loop counter for 1 ms (240 @ 4.77 MHz)
  1467. pcwai1: sub     cx,1            ; inner loop takes 20 clock cycles
  1468.         jnz     pcwai1
  1469.         dec     ax              ; outer loop counter
  1470.         jnz     pcwai0          ; wait another millisecond
  1471.         pop     cx
  1472.         ret
  1473. pcwait  endp
  1474.  
  1475. ; set the current port.
  1476. ; Note: serial port addresses are found by looking in memory at 40:00h and
  1477. ; following three words for COM1..4, resp. All UARTS are assumed to follow
  1478. ; std IBM addresses relative to 03f8h for COM1, and actual address are offset
  1479. ; from value found in segment 40h. Global byte flags.comflg is 1,2,3,4 for
  1480. ; COM1..4, and is 'N' for Network.
  1481. ; If address 02f8h is found in 40:00h then name COM1 is retained but COM2
  1482. ;  addressing is used to access the UART and a notice is displayed. IRQ 3
  1483. ; or IRQ 4 is sensed automatically for any COMx port.
  1484. COMS    PROC    NEAR
  1485.         mov     dx,offset comptab       ; table of legal comms ports
  1486.         mov     bx,0                    ; no extra help text
  1487.         mov     ah,cmkey                ; parse key word
  1488.         call    comnd
  1489.          jmp    r                       ;  failed
  1490.         mov     temp,bx
  1491.         cmp     bl,'N'                  ; NetBios network?
  1492.         je      comstrt                 ; yes, get another item for networks
  1493.         cmp     bl,'U'                  ; Ungermann Bass net?
  1494.         je      comstrt                 ; e = yes
  1495.         mov     ah,cmcfm                ; non-network
  1496.         call    comnd                   ; Get a confirm
  1497.          jmp    r                       ;  Didn't get a confirm
  1498.          nop
  1499.         mov     bx,temp
  1500. COMSTRT:cmp     portin,-1               ; first time here?
  1501.         jne     comst1                  ; ne = no
  1502.         mov     portin,0                ; say have been here before
  1503. comst1: mov     temp,bx
  1504.         cmp     bl,'N'                  ; NetBios network?
  1505.         jne     comst2                  ; ne = no
  1506.         jmp     comsn                   ; yes, get another item for networks
  1507. comst2: cmp     bl,'U'                  ; Ungermann Bass net?
  1508.         jne     comst3                  ; ne = no
  1509.         jmp     comsub
  1510. comst3: cmp     flags.comflg,'N'        ; have been running on network?
  1511.         jne     coms1b                  ; ne = no
  1512.                                         ; turn off sources of net interrupts
  1513.         mov     bx,offset can           ; cancel outstanding requests
  1514.         mov     can.scb_cmd,ncancel     ; set cancel op code
  1515.         cmp     lposted,1               ; listen outstanding?
  1516.         jne     coms1a                  ; ne = no
  1517.         mov     can.scb_baddr,offset lsn ; cancel listen
  1518.         call    session
  1519.         mov     lposted,0
  1520. coms1a: cmp     rposted,1               ; receive outstanding?
  1521.         jne     coms1b                  ; ne = no
  1522.         mov     can.scb_baddr,offset rcv ; cancel receive
  1523.         call    session
  1524.         mov     rposted,0               ; clear interlock flag
  1525.  
  1526. coms1b: call    serrst                  ; close current comms port
  1527.         mov     bx,temp                 ; get port number/letter
  1528.         mov     flags.comflg,bl         ; remember port number
  1529.         mov     bh,0
  1530.         mov     bl,flags.comflg         ; get COMx number (1-4)
  1531.         push    bx                      ; Set UART port addresses
  1532.         mov     ax,bx                   ; get COMx (1-4)
  1533.         cmp     al,'1'                  ; ascii numbered Bios port?
  1534.         jb      coms3                   ; b = no
  1535.         sub     al,'0'                  ; remove ascii bias for portinfo
  1536. coms3:  dec     ax                      ; count ports from zero
  1537.         mov     bx,type prtinfo         ; size of each portinfo structure
  1538.         mul     bx                      ; times port number
  1539.         add     ax,offset port1         ; plus start of COM1
  1540.         mov     portval,ax              ; points to our current port struct
  1541.         pop     bx                      ; restore registers
  1542.         cmp     bl,' '                  ; doing forced Bios?
  1543.         jb      coms4                   ; b = no, hardware
  1544.         mov     clone,'B'               ; set clone flag for Bios usage
  1545.         jmp     rskp                    ; all done
  1546.  
  1547. coms4:  push    bx                      ; save register
  1548.         push    es
  1549.         mov     ax,40h          ; look at RS232_base [bx] in Bios area 40:00h
  1550.         mov     es,ax
  1551.         dec     bl                      ; count com1 as bl = 0, etc
  1552.         mov     bh,0                    ; clear high byte
  1553.         shl     bx,1                    ; make bx a word index
  1554.         mov     ax,es:[bx]              ; get modem base address into ax
  1555.         pop     es
  1556.         pop     bx
  1557.         or      ax,ax                   ; is address zero?
  1558.         je      comsf                   ; e = yes, no serial port
  1559. comsc:                                  ; hardware tests
  1560.         mov     modem.mddat,ax  ; set base address (also data address) 03f8h
  1561.         add     ax,3                    ; increment to command port 03fbh
  1562.         mov     modem.mdcom,ax          ; set line control register address
  1563.         mov     brkadr,ax               ; where to send break command
  1564.         add     ax,2                    ; increment to status port 03fdh
  1565.         mov     modem.mdstat,ax         ; set line-status port address
  1566.  
  1567.         call    chkport                 ; get type of UART support (for Clone)
  1568.         jnc     comsu                   ; nc = has a real 8250 uart
  1569.         add     flags.comflg,'0'        ; COMn to BIOSn
  1570.         push    ax                      ; else tell user about Bios pathway
  1571.         push    dx
  1572.         mov     ah,prstr
  1573.         mov     dx,offset biosmsg
  1574.         int     dos
  1575.         pop     dx
  1576.         pop     ax
  1577.         jmp     rskp
  1578.  
  1579. comsu:  call    chkint                  ; find IRQ for the port
  1580.         jc      comsf                   ; c = not found, an error conditon
  1581.         jmp     rskp
  1582.  
  1583. comsf:  mov     dx,offset badprt        ; say port is not available
  1584.         mov     ah,prstr
  1585.         int     dos
  1586.         mov     al,flags.comflg         ; port ident character
  1587.         cmp     al,' '                  ; binary for COM series
  1588.         jae     comsf1                  ; ae = no
  1589.         mov     dx,offset compt         ; display COM
  1590.         int     dos
  1591.         mov     ah,conout
  1592.         mov     dl,flags.comflg
  1593.         add     dl,'0'                  ; display port number
  1594.         int     dos
  1595.         jmp     comsf3
  1596. comsf1: cmp     al,'9'                  ; ascii numeric for Bios series?
  1597.         ja      comsf2                  ; a = no
  1598.         mov     dx,offset biospt        ; display BIOS
  1599.         int     dos
  1600.         mov     ah,conout
  1601.         mov     dl,flags.comflg         ; ascii port number
  1602.         int     dos
  1603.         jmp     comsf3
  1604. comsf2: mov     dx,offset unkpt         ; unknown type
  1605.         int     dos
  1606. comsf3: mov     flags.comflg,0          ; bad port, reassign to null port
  1607.         mov     ah,prstr
  1608.         mov     dx,offset badprt2       ; the rest of the message
  1609.         mov     ah,prstr
  1610.         int     dos
  1611.         stc                             ; say error
  1612.         jmp     rskp
  1613.                                         ; NetBios Network support
  1614. comsn:  mov     ah,cmfile               ; get a word (remote node name)
  1615.         mov     dx,offset nambuf        ; work buffer
  1616.         mov     word ptr nambuf,0       ; insert terminator
  1617.         mov     bx,offset nethlp        ; help message
  1618.         call    comnd                   ; get the name
  1619.          nop
  1620.          nop
  1621.          nop
  1622.         xchg    ah,al                   ; put byte count in al
  1623.         xor     ah,ah                   ; clear junk
  1624.         mov     temp,ax                 ; save number of chars entered
  1625.         mov     ah,cmcfm
  1626.         call    comnd                   ; Get a confirm
  1627.          jmp    r                       ;  Didn't get a confirm
  1628.          nop
  1629.         call    serrst                  ; reset serial port
  1630.         call    chknet                  ; start network usage
  1631.         cmp     pcnet,0                 ; is network alive (non-zero)?
  1632.         jne     comsn4                  ; ne = yes
  1633.         stc
  1634.         jmp     rskp                    ; return failure
  1635.  
  1636. comsn4: mov     portval,offset portn ; set Network port data structure address
  1637.         mov     flags.comflg,'N'        ; Set the comm port flag
  1638.         call    chkport                 ; set type of port support
  1639.         clc                             ; return success
  1640.         jmp     rskp                    ; End NetBios
  1641.  
  1642.                                         ; Ungermann-Bass terminal port [ohl +]
  1643. comsub: mov     ah,cmcfm
  1644.         call    comnd                   ; Get a confirm
  1645.          jmp    r                       ;  Didn't get a confirm
  1646.          nop
  1647.         call    serrst                  ; reset serial port
  1648.         call    chkub                   ; check UB network presence
  1649.         jnc     comsub1                 ; nc = present
  1650.         stc
  1651.         jmp     rskp                    ; return failure
  1652.  
  1653. comsub1:call    netclose                ; better close NetBios parts NOW!
  1654.         mov     portval,offset portn ; set Network port data structure address
  1655.         mov     flags.comflg,'U'        ; Set the comm port flag
  1656.         mov     pcnet,2                 ; network is present and active
  1657.         mov     lclexit,offset ubclose  ; address to close network
  1658.         call    chkport                 ; get type of port support
  1659.         clc                             ; return success
  1660.         jmp     rskp                    ; End Ungermann Bass    [ohl -]
  1661. COMS    ENDP
  1662.  
  1663. ; Check which Interrupt ReQuest line the port uses. Technique: allow interrupt
  1664. ; on transmitter holding register empty, test for that condition first with
  1665. ; IRQ 4 and then IRQ 3. Returns with IRQ values set and carry clear if success
  1666. ; or carry set if failure. [jrd]
  1667. chkint  proc    near
  1668.         cmp     flags.comflg,2          ; COM1 or COM2?
  1669.         jbe     chkin2                  ; be = yes, use standard IRQ's
  1670.         mov     modem.mddis,MDMINTC     ; IRQ 4 test. mask to disable IRQ 4
  1671.         mov     modem.mden,MDMINTO      ; mask to enable IRQ 4
  1672.         mov     modem.mdmeoi,20h        ; use general in case we guess wrong
  1673.         mov     modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch)
  1674.         mov     intkind,0               ; clear interrupt cause
  1675.         call    serini                  ; setup port for IRQ 4
  1676.         jc      chkint2                 ; c = failure
  1677.         mov     dx,modem.mddat
  1678.         inc     dx                      ; interrupt enable reg (3f9h)
  1679.         mov     al,2                    ; set xmtr holding reg empty interrupt
  1680.         out     dx,al
  1681.         mov     ax,1                    ; wait one millisec for interrupt
  1682.         call    pcwait                  ;  to occur
  1683.         test    intkind,2               ; check cause of interrupt, ours?
  1684.         jz      chkint2                 ; z = no, try other IRQ
  1685.         call    serrst                  ; reset port
  1686.         mov     modem.mdmeoi,EOICOM     ; use specific EOI for IRQ4 level
  1687.         clc                             ; this setup worked
  1688.         ret
  1689.                                         ; IRQ 3 test
  1690. chkint2:call    serrst                  ; reset port
  1691.         mov     modem.mddis,MDINTC2     ; mask to disable IRQ 3
  1692.         mov     modem.mden,MDINTO2      ; mask to enable IRQ 3
  1693.         mov     modem.mdmeoi,20h        ; use general in case we guess wrong
  1694.         mov     modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1695.         mov     intkind,0               ; clear interrupt cause
  1696.         call    serini                  ; setup port for IRQ 3
  1697.         jc      chkin2                  ; c = failure
  1698.         mov     dx,modem.mddat
  1699.         inc     dx                      ; interrupt enable reg (3f9h)
  1700.         mov     al,2                    ; set xmtr holding reg empty interrupt
  1701.         out     dx,al
  1702.         mov     ax,1                    ; wait one millisec for interrupt
  1703.         call    pcwait                  ;  to occur
  1704.         test    intkind,2               ; check cause of interrupt, ours?
  1705.         jz      chkin2                  ; z = no, so no interrupts for port
  1706.         call    serrst                  ; reset port
  1707.         mov     modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1708.         clc                             ; this setup worked
  1709.         ret
  1710.  
  1711. chkin2: call    serrst                  ; reset port, auto test did not work
  1712.         cmp     flags.comflg,1          ; COM1?
  1713.         je      chkin4                  ; e = yes, use IRQ 4
  1714.         cmp     isps2,0                 ; IBM PS/2 Model 50 or above?
  1715.         jne     chkin3                  ; ne = yes, other COMs use IRQ 3
  1716.         cmp     flags.comflg,3          ; COM2, COM3, or COM4?
  1717.         je      chkin4                  ; e = COM3, use IRQ 4
  1718.         jmp     short chkin3            ; else COM2 or COM4, use IRQ 3
  1719. chkin4: cmp     modem.mddat,02f8h       ; really COM2 material for PCjr?
  1720.         je      chkin3                  ; e = yes, use COM2 addresses
  1721.         mov     modem.mdmeoi,EOICOM     ; use specific EOI for IRQ4 level
  1722.         mov     modem.mddis,MDMINTC     ; IRQ 4 test. mask to disable IRQ 4
  1723.         mov     modem.mden,MDMINTO      ; mask to enable IRQ 4
  1724.         mov     modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch)
  1725.         jmp     short chkin5
  1726. chkin3: mov     modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1727.         mov     modem.mddis,MDINTC2     ; mask to disable IRQ 3
  1728.         mov     modem.mden,MDINTO2      ; mask to enable IRQ 3
  1729.         mov     modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1730. chkin5: clc
  1731.         ret
  1732. chkint  endp
  1733.  
  1734. ; Test presently selected serial port for having a real 8250 UART.
  1735. ; Return carry clear and clone = 0 if 8250 present,
  1736. ;  else carry set and clone = 'B' for system Bios or
  1737. ;  carry set and clone = 'N' for network.
  1738. ; Method is to check UART's Interrupt Identification Register for high
  1739. ; five bits being zero; IBM does it this way. Assumes port structure
  1740. ; has been initialized with addresses of UART.  21 Feb 1987 [jrd]
  1741. ; 29 May 1987 Add double check by reading Line Status Register. [jrd]
  1742.  
  1743. chkport proc    near
  1744.         cmp     portval,offset portn    ; network?
  1745.         je      chkporn                 ; e = yes
  1746.         push    ax
  1747.         push    dx
  1748.         cmp     flags.comflg,0          ; undefined port?
  1749.         je      chkpor1                 ; e = yes, assume Bios clone
  1750.         mov     dx,modem.mdcom  ; address of UART line control reg (3FBh/2FBh)
  1751.         sub     dx,1            ; Interupt Identification Register address
  1752.         in      al,dx                   ; read UART's IIR
  1753.         test    al,0f8h                 ; are any of high 5 bits set?
  1754.         jnz     chkpor1                 ; nz = yes, not an 8250
  1755.         mov     dx,modem.mdstat         ; line status register
  1756.         in      al,dx                ; read to clear UART BI, FE, PE, OE bits
  1757.         jmp     $+2                     ; pause, for chip access timing
  1758.         in      al,dx                   ; these bits should be cleared
  1759.         test    al,8eh                  ; are they cleared?
  1760.         jnz     chkpor1                 ; nz = no, not an 8250
  1761.         mov     clone,0                 ; clear clone flag
  1762.         pop     dx
  1763.         pop     ax
  1764.         clc                             ; clear carry (say 8250)
  1765.         ret
  1766. chkpor1:pop     dx
  1767.         pop     ax
  1768.         mov     clone,'B'               ; set clone flag
  1769.         stc                             ; set carry (say no 8250)
  1770.         ret
  1771. chkporn:push    ax                      ; Networking
  1772.         mov     al,flags.comflg         ; get port letter
  1773.         mov     clone,al
  1774.         pop     ax
  1775.         stc                             ; set carry (say no 8250)
  1776.         ret
  1777. chkport endp
  1778. ;;;;;;;;;;;;;;;;;;;;;; end of part one of msxibm.asm
  1779. ;;;;;;;;;;;;;;;;;;;;;; start part two of msxibm.asm
  1780.  
  1781. ; Set the baud rate for the current port, based on the value
  1782. ; in the portinfo structure.  Returns normally.
  1783. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1784.  
  1785. DOBAUD  PROC    NEAR
  1786.         cmp     portin,-1               ; port not used yet?
  1787.         jne     dobd3                   ; ne = no, go get rate
  1788.         mov     bl,flags.comflg         ; pass current port ident
  1789.         call    comstrt                 ; do SET PORT command now
  1790.          ret                            ; failed to set port
  1791.          nop
  1792.          nop
  1793. dobd3:  push    ax                      ; save some regs
  1794.         push    bx
  1795.         push    dx
  1796.         call    chkport         ; check port for real 8250 UART (clone = 0)
  1797.         cmp     flags.comflg,'N'        ; Netbios?
  1798.         je      dobd1                   ; e = yes, do nothing here
  1799.         cmp     flags.comflg,'U'        ; UB network?
  1800.         je      dobd1                   ; e = yes
  1801.         mov     bx,portval              ; pointer to port data structure
  1802.         mov     temp,ax                 ; Don't overwrite previous rate
  1803.         mov     ax,[bx].baud            ; Check if new rate is valid
  1804.         shl     ax,1                    ; make a word index
  1805.         mov     bx,offset bddat         ; Start of table
  1806.         cmp     clone,'B'               ; running on clone?
  1807.         jne     dobd0a                  ; ne = no
  1808.         mov     bx,offset clbddat       ; use Bios speed parameters for clone
  1809. dobd0a: add     bx,ax
  1810.         mov     ax,[bx]                 ; The data to output to port
  1811.         cmp     ax,0FFH                 ; Unimplemented baud rate
  1812.         jne     dobd0
  1813.         mov     ah,prstr
  1814.         mov     dx,offset badbd         ; Give an error message
  1815.         int     dos
  1816.         jmp     dobd1
  1817.  
  1818. dobd0:  cmp     clone,0                 ; running on a real uart?
  1819.         je      dobd2                   ; e = the real thing
  1820.         mov     dx,0            ; assume port 1 Clone: find current port
  1821.         mov     dl,flags.comflg         ; get coms port (1..4)
  1822.         or      dl,dl                   ; zero (undefined port)?
  1823.         jz      dobd1                   ; z = yes, just exit
  1824.         and     dl,7                    ; use lower three bits
  1825.         dec     dl                      ; count ports as 0..3 for Bios
  1826.         mov     ah,0                    ; set serial port
  1827.         int     rs232                   ; Bios: set the parameters
  1828.         jmp     dobd1                   ; and exit
  1829.  
  1830. dobd2:  mov     temp,ax                 ; Remember value to output
  1831.         mov     dx,modem.mdcom          ; LCR -- Initialize baud rate
  1832.         in      al,dx                   ; get it
  1833.         mov     bl,al                   ; make a copy
  1834.         or      ax,80H          ; turn on DLAB bit to access divisor part
  1835.         out     dx,al
  1836.         mov     dx,modem.mddat
  1837.         mov     ax,temp                 ; set the baud rate divisor, low byte
  1838.         out     dx,al
  1839.         inc     dx                      ; next address for high part
  1840.         mov     al,ah                   ; set high part of divisor
  1841.         out     dx,al
  1842.         mov     dx,modem.mdcom          ; LCR again
  1843.         mov     al,bl                   ; get original setting from bl
  1844.         out     dx,al                   ; restore it
  1845. dobd1:  pop     dx                      ; restore regs
  1846.         pop     bx
  1847.         pop     ax
  1848.         ret
  1849. DOBAUD  ENDP
  1850.  
  1851. ; Get the current baud rate from the serial card and set it
  1852. ; in the portinfo structure for the current port.  Returns normally.
  1853. ; This is used during initialization.
  1854. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1855.  
  1856. GETBAUD PROC    NEAR
  1857.         cmp     portin,-1               ; port not used yet?
  1858.         jne     getb4                   ; ne = no, go get rate
  1859.         mov     bl,flags.comflg         ; pass current port ident
  1860.         call    comstrt                 ; do SET PORT command now
  1861.          ret                            ; failed to set port
  1862.          nop
  1863.          nop
  1864. getb4:  cmp     clone,0                 ; non-clone
  1865.         je      getbud                  ; e = yes, real thing
  1866.         ret                             ; have semi-clone, no bios feedback
  1867. getbud: push    ax                      ; save some regs
  1868.         push    bx
  1869.         push    cx
  1870.         push    dx
  1871.         mov     dx,modem.mdcom       ; Get current Line Control Register value
  1872.         in      al,dx
  1873.         mov     bl,al                   ; Save it
  1874.         or      ax,80H                ; Turn on to access baud rate generator
  1875.         out     dx,al
  1876.         mov     dx,modem.mddat          ; Divisor latch
  1877.         inc     dx
  1878.         in      al,dx                   ; Get hi order byte
  1879.         mov     ah,al                   ; Save here
  1880.         dec     dx
  1881.         in      al,dx                   ; Get lo order byte
  1882.         push    ax
  1883.         mov     dx,modem.mdcom          ; Line Control Register
  1884.         mov     al,bl                   ; Restore old value
  1885.         out     dx,al
  1886.         pop     ax
  1887.         cmp     ax,0FFFFH               ; Who knows what this is
  1888.         je      getb2
  1889.         mov     bx,offset bddat         ; Find rate's offset into table
  1890.         mov     cl,0                    ; Keep track of index
  1891. getb0:  cmp     ax,[bx]
  1892.         je      getb1
  1893.         inc     cl
  1894.         cmp     cl,baudlen              ; At the end of the list
  1895.         jge     getb2
  1896.         add     bx,2
  1897.         jmp     getb0
  1898. getb1:  mov     ch,0
  1899.         mov     bx,portval
  1900.         mov     [bx].baud,cx            ; Set baud rate
  1901.         jmp     getb3
  1902. getb2:  mov     ah,prstr
  1903.         mov     dx,offset erms40
  1904.         int     dos
  1905. getb3:  pop     dx                      ; restore regs
  1906.         pop     cx
  1907.         pop     bx
  1908.         pop     ax
  1909.         ret
  1910. GETBAUD ENDP
  1911.  
  1912. ; Get Char from serial port buffer.
  1913. ; skip returns if no character available at port,
  1914. ; otherwise returns with char in al, # of chars in buffer in dx.
  1915. ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
  1916. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1917. ; 25 April 1987 Add Netbios support, remove test for NUL and DEL. [jrd]
  1918. PRTCHR  PROC    NEAR
  1919.         cmp     holdscr,0               ; Holdscreen in effect?
  1920.         jne     prtch0a                 ; ne = yes, do not read
  1921.         call    chkxon                  ; see if we need to xon
  1922.         cmp     clone,'B'               ; running on a semi-clone?
  1923.         je      prtch6                  ; e = yes
  1924.         cmp     clone,'N'               ; running on NetBios network?
  1925.         je      prtchn                  ; e = yes
  1926.         cmp     clone, 'U'              ; running Ungermann-Bass port? [ohl]
  1927.         jne     prtch0                  ; ne = no
  1928. prtchn: test    xofsnt,usron            ; user level xoff sent?
  1929.         jnz     prtch0a                 ; nz = yes, suppress reading here
  1930.         cmp     count,mntrgl            ; below low water mark?
  1931.         ja      prtch1                  ; a = no, read current buffer
  1932.         cmp     clone,'U'               ; UB network?
  1933.         jne     prtchn1                 ; ne = no
  1934.         call    ubrecv                  ; do a UB receive
  1935.         jmp     short prtch0
  1936. prtchn1:call    receive                 ; do a NetBios receive (asynchronous)
  1937.         jc      prtch0a                 ; c = failure
  1938. prtch0: cmp     count,0                 ; any characters available?
  1939.         jnz     prtch1                  ; nz = yes, get one
  1940. prtch0a:mov     dx,0                    ; return count of zero
  1941.         jmp     rskp                    ; No data - check console
  1942. prtch1: push    si                      ; save si
  1943.         cli             ; interrupts off, to keep srcpnt & count consistent
  1944.         mov     si,srcpnt           ; address of next available slot in buffer
  1945.         sub     si,count            ; minus number of unread chars in buffer
  1946.         cmp     si,offset source        ; located before start of buf?
  1947.         jae     prtch2                  ; ae = no
  1948.         add     si,bufsiz               ; else do arithmetic modulo bufsiz
  1949. prtch2: mov     al,byte ptr [si]        ; get a character into al
  1950.         dec     count                   ; one less unread char now
  1951.         sti                             ; interrupts back on now
  1952.         pop     si
  1953.         mov     dx,count                ; return # of chars in buffer
  1954.         jmp     prtch12                 ; screen delivered characters
  1955.  
  1956. prtch6:                                 ; Semi-clone, use Bios calls
  1957.         mov     dx,0            ; assume port 1 Clone: find current port
  1958.         mov     dl,flags.comflg         ; get port number (1..4)
  1959.         or      dl,dl                   ; zero (no such port)?
  1960.         jz      prtch8                  ; z = yes, don't access it
  1961.         and     dl,7                    ; use low three bits
  1962.         dec     dl                      ; address ports as 0..3 for Bios
  1963. prtch7: mov     ah,3                    ; check port status
  1964.         int     rs232                   ; Clone Bios call
  1965.         test    ah,mdminp               ; data ready?
  1966.         jnz     prtch9                  ; nz = yes, get one
  1967. prtch8: mov     dx,0                    ; return count of zero
  1968.         mov     count,dx
  1969.         jmp     rskp                    ; No data
  1970. prtch9: mov     ah,2                    ; receive a char into al
  1971.         int     rs232                   ; Clone Bios call
  1972.         test    ah,8ch                  ; timeout, framing error, parity error?
  1973.         jnz     prtch8                  ; nz = error, no char
  1974.         mov     dx,1
  1975.         mov     count,dx                ; one char received into al
  1976.         cmp     al,flowoff              ; acting on Xoff?
  1977.         jne     prtch10                 ; ne = no, go on
  1978.         cmp     xofsnt,0                ; have we sent an outstanding XOFF?
  1979.         jne     prtch8                  ; ne = yes, ignore (possible echo)
  1980.         mov     xofrcv,bufon            ; Set the flag saying XOFF received
  1981.         jmp     prtch8                  ;  and exit
  1982. prtch10:cmp     al,flowon               ; acting on Xon?
  1983.         jne     prtch12                 ; ne = no, go on
  1984.         mov     xofrcv,off              ; Clear the XOFF received flag
  1985.         jmp     short prtch8            ; no data to return
  1986. prtch12:test    flags.debug,logses      ; debug mode?
  1987.         jnz     prtch14                 ; nz = yes, pass all chars
  1988.         cmp     rxtable+256,0           ; translation turned off?
  1989.         jne     prtch14                 ; ne = table is on, pass all chars
  1990.         cmp     al,0                    ; NUL?
  1991.         je      prtch13                 ; e = yes, ignore it
  1992.         cmp     tekflg,0                ; Tek emulation active?
  1993.         jne     prtch14                 ; ne = yes, pass DEL
  1994.         cmp     al,DEL                  ; DEL char
  1995.         jne     prtch14                 ; ne = no, pass char
  1996. prtch13:mov     dx,0
  1997.         jmp     rskp                    ; no chars
  1998. prtch14:ret                             ; return char in al
  1999. PRTCHR  ENDP
  2000.  
  2001. ; Network Receive packet routine. Request a net packet with no-wait option.
  2002. ; Return carry clear if success. If failure, reset serial port (Server mode
  2003. ; reinits serial port) and return carry set. No entry setup needed.
  2004. RECEIVE PROC    NEAR                    ; receive network session pkt
  2005.         cmp     pcnet,1                 ; net ready yet?
  2006.         jbe     receiv3                 ; be = no, declare a broken session
  2007.         cmp     rposted,1               ; is a request outstanding now?
  2008.         jae     receiv4                 ; ae = yes, don't do another
  2009.         mov     rposted,1               ; say posting a receive now
  2010.         mov     rcv.scb_length, length rcvbuf ; length of input buffer
  2011.         mov     rcv.scb_cmd,nreceive+nowait   ; receive, no wait
  2012.         push    bx
  2013.         mov     bx,offset rcv           ; setup pointer to scb
  2014.         call    session
  2015.         pop     bx                      ; tests below SHOULD take time
  2016.         cmp     rcv.scb_err,0           ; success?
  2017.         je      receiv4                 ; e = yes
  2018.         cmp     rcv.scb_err,npending    ; pending receive?
  2019.         je      receiv4                 ; e = yes
  2020.         push    ax                      ; wait one millisec before retesting
  2021.         push    cx
  2022.         mov     ax,1
  2023.         call    pcwait
  2024.         pop     cx
  2025.         pop     ax
  2026.         cmp     rcv.scb_err,06h         ; message incomplete?
  2027.         je      receiv4                 ; e = is ok (response posted later)
  2028.         cmp     rcv.scb_err,0        ; success now? (here for latency effects)
  2029.         je      receiv4                 ; e = yes
  2030.         cmp     rcv.scb_err,18h         ; session ended abnormally?
  2031.         jbe     receiv3                 ; e = yes, b = other normal errors
  2032.         push    ax                      ; save regs around error display
  2033.         push    dx
  2034.         mov     ah,prstr
  2035.         mov     dx,offset recmsg        ; give error message
  2036.         int     dos
  2037.         mov     al,rcv.scb_err          ; get error code
  2038.         call    hexout                  ; show error code
  2039.         pop     dx
  2040.         pop     ax
  2041.                                         ; Error return
  2042. receiv3:mov     pcnet,1                 ; say session is broken
  2043.         call    serrst                  ; reset serial port
  2044.         test    flags.remflg,dserver    ; server mode?
  2045.         jz      receiv3a                ; z = no
  2046.         call    serini                  ; reinitialize it for new session
  2047. receiv3a:stc                            ; say failure to receive
  2048.         ret
  2049. receiv4:clc                             ; carry clear = success
  2050.         ret
  2051. RECEIVE ENDP
  2052.  
  2053. ; Network Receive post processing interrupt routine.
  2054. ; Copy chars from rcvbuf to circular buffer source, act on xon/xoff,
  2055. ; clear rposted interlock flag. At entry, CS is our code segment,
  2056. ; es:bx points to scb, netbios stack, interrupts are off.
  2057. RPOST   PROC    NEAR            ; network receive post interrupt routine
  2058.         push    ds              ; transfers chars from net buf rcvbuf to
  2059.         push    ax              ; main circular buffer source
  2060.         push    bx
  2061.         push    cx
  2062.         push    dx
  2063.         push    si
  2064.         mov     ax,datas                ; reestablish datas segment
  2065.         mov     ds,ax
  2066.         mov     cx,rcv.scb_length       ; get returned byte count
  2067.         jcxz    rpost6                  ; z = nothing there
  2068.         mov     dh,flowon             ; flow control characters, for quick ref
  2069.         mov     dl,flowoff
  2070.         mov     si,offset rcvbuf        ; source of text
  2071.         mov     bx,srcpnt               ; address of buffer storage slot
  2072.         cld
  2073. rpost1: lodsb                           ; get byte from rcvbuf to al
  2074.         or      dx,dx                   ; doing flow control?
  2075.         jz      rpost3                  ; z = no
  2076.         mov     ah,al                   ; get copy of character
  2077.         and     ah,parmsk               ; strip parity, if any, before testing
  2078.         cmp     ah,dl                   ; acting on Xoff?
  2079.         jne     rpost2                  ; ne = Nope, go on
  2080.         cmp     xofsnt,0                ; have we sent an XOFF?
  2081.         jne     rpost5                  ; ne = yes, ignore this XOFF char
  2082.         mov     xofrcv,bufon        ; Set the flag saying buffer XOFF received
  2083.         jmp     rpost5                  ;  and skip this character
  2084. rpost2: cmp     ah,dh                   ; acting on Xon?
  2085.         jne     rpost3                  ; ne = no, go on
  2086.         mov     xofrcv,off              ; Clear the XOFF received flag
  2087.         jmp     rpost5                  ;  and skip this character
  2088.  
  2089. rpost3: mov     byte ptr [bx],al       ; store the new char in buffer "source"
  2090.         inc     bx
  2091.         cmp     bx,offset source + bufsiz ; beyond end of buffer?
  2092.         jb      rpost4                  ; b = not past end
  2093.         mov     bx,offset source        ; wrap buffer around
  2094. rpost4: cmp     count,bufsiz            ; filled already?
  2095.         jae     rpost5                  ; ae = yes
  2096.         inc     count                   ; no, add a char
  2097. rpost5: loop    rpost1
  2098.         mov     srcpnt,bx               ; update pointer to next free slot
  2099. rpost6: mov     rposted,0               ; clear interlock flag
  2100.         pop     si
  2101.         pop     dx
  2102.         pop     cx
  2103.         pop     bx
  2104.         pop     ax
  2105.         pop     ds
  2106.         iret                            ; return from interrupt
  2107. RPOST   endp
  2108.  
  2109. ; Ungermann-Bass NETCI port receive characters routine.  Receive one or more
  2110. ; characters.  Calls the Rpost routine to transfer character to main source
  2111. ; circular buffer.  Return carry clear if success.
  2112. UBRECV  PROC    near
  2113.         push    ax
  2114.         push    bx
  2115.         push    cx
  2116.         push    es
  2117.         mov     ax, datas
  2118.         mov     es, ax                  ; es:bx will point to rcvbuf
  2119.         mov     ax, nciread             ; function 1 (receive) port 0    [ohl]
  2120.         mov     bx, offset rcvbuf
  2121.         mov     cx, length rcvbuf
  2122.         int     netci                   ; get characters                 [ohl]
  2123.         stc
  2124.         jcxz    ubrec1                  ; cx = z = nothing to do
  2125.         mov     rcv.scb_length, cx      ; prepare for rpost call         [ohl]
  2126.         mov     bx, offset rcv
  2127.         pushf                           ; simulate interrupt             [ohl]
  2128.         push    cs                      ; rpost is an interrupt routine (iret)
  2129.         call    rpost                   ; do Near call with preset stack
  2130.         clc
  2131. ubrec1: pop     es
  2132.         pop     cx
  2133.         pop     bx
  2134.         pop     ax
  2135.         ret
  2136. UBRECV  ENDP
  2137.  
  2138. ; Put the char in AH to the serial port.  This assumes the
  2139. ; port has been initialized.  Should honor xon/xoff.  Skip returns on
  2140. ; success, returns normally if the character cannot be written.
  2141. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  2142. ; 25 April 1987 Add Netbios support [jrd]
  2143. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  2144. ; prevent confusion of flow control logic at top of outchr; used by receiver
  2145. ; buffer high/low water mark flow control code. [jrd]
  2146. OUTCHR  PROC    NEAR
  2147.         cmp     flowoff,0               ; Are we doing flow control
  2148.         je      outch2                  ; No, just continue
  2149.         cmp     ah,flowoff              ; sending xoff?
  2150.         jne     outch1                  ; ne = no
  2151.         mov     xofsnt,usron            ; indicate user level xoff being sent
  2152.         jmp     outch1b
  2153. outch1: cmp     ah,flowon               ; user sending xon?
  2154.         jne     outch1b                 ; ne = no
  2155.         mov     xofsnt,off           ; say an xon has been sent (cancels xoff)
  2156. outch1b:cmp     xofrcv,off              ; Are we being held (xoff received)?
  2157.         je      outch2                  ; e = no - it's OK to go on
  2158.         cmp     flags.timflg,0          ; is timer off?
  2159.         je      outch2                  ; e = yes, no timeout period
  2160.         push    cx                      ; save reg
  2161.         mov     ch,trans.rtime          ; receive timeout interval (sec)
  2162.         mov     cl,0                    ;  convert to 4 millsec increments
  2163.         jcxz    outch1c                 ; z = no timeout wanted
  2164.  
  2165. outch1a:cmp     xofrcv,off              ; Are we being held (xoff received)?
  2166.         je      outch1c                 ; e = no - it's OK to go on
  2167.         push    ax
  2168.         mov     ax,4                    ; 4 millisec wait loop
  2169.         call    pcwait
  2170.         pop     ax
  2171.         loop    outch1a                 ; and try it again
  2172.         mov     xofrcv,off              ; timed out, force it off and fall thru
  2173. outch1c:pop     cx                      ; end of flow control section
  2174.                      ; OUTCH2 is entry point for sending without flow control
  2175. OUTCH2: mov     al,ah                   ; Parity routine works on AL
  2176.         call    dopar                   ; Set parity appropriately
  2177.         mov     ah,al                   ; Don't overwrite character with status
  2178. outch3: cmp     clone,0                 ; real uart?
  2179.         je      outch3a                 ; e = yes
  2180.         cmp     clone,'N'               ; network?
  2181.         je      outch8                  ; e = yes, using netbios
  2182.         cmp     clone,'U'               ; Ungermann Bass network?
  2183.         je      outch8                  ; e = yes
  2184.         jmp     outch6                  ; default for others ('B' clones)
  2185. outch3a:push    cx                      ; Save registers
  2186.         push    dx
  2187.         sub     cx,cx
  2188. outch3b:mov     dx,modem.mdstat         ; Get port status
  2189.         in      al,dx
  2190.         test    al,20H                  ; Transmitter ready?
  2191.         jnz     outch4                  ; Yes
  2192.         jmp     $+2                     ; use time, prevent overdriving UART
  2193.         jmp     $+2
  2194.         loop    outch3b
  2195.          jmp    outch5                  ; Timeout
  2196. outch4: mov     al,ah                   ; Now send it out
  2197.         mov     dx,modem.mddat          ; use a little time
  2198.         jmp     $+2
  2199.         out     dx,al
  2200.         pop     dx                      ; exit success
  2201.         pop     cx
  2202.         jmp     rskp
  2203. outch5: pop     dx                      ; exit failure
  2204.         pop     cx
  2205.         ret
  2206.                                 ; finish up for semi-clones, use Bios calls
  2207. outch6: push    cx                      ; Clone: find current port
  2208.         push    dx
  2209.         mov     dx,0                    ; assume port 1
  2210.         mov     dl,flags.comflg         ; get port number (1..4)
  2211.         or      dl,dl                   ; zero (no such port)?
  2212.         jz      outch5                  ; z = yes, don't access it
  2213.         and     dl,7                    ; use lower three bits
  2214.         dec     dl                      ; address ports as 0..3 for Bios
  2215.         mov     al,ah                   ; Now send it out
  2216.         mov     ah,1                    ; send char
  2217.         int     rs232                   ; Clone: bios send
  2218.         pop     dx                      ; exit success
  2219.         pop     cx
  2220.         jmp     rskp
  2221. outch8:                         ; Network sending, buffered and single char
  2222.         push    bx
  2223.         mov     bx,xmtcnt               ; count of chars in buffer
  2224.         mov     xmtbufx[bx],ah          ; put char in buffer
  2225.         pop     bx
  2226.         inc     xmtcnt                  ; count of items in this buffer
  2227.         cmp     xmtcnt,length xmtbuf    ; is buffer full now?
  2228.         jae     outch9                  ; ae = buffer is full, send it now
  2229.         cmp     ah,trans.seol           ; end of packet?
  2230.         je      outch9                  ; e = yes, send buffer
  2231.         cmp     ah,flowon               ; flow control?
  2232.         je      outch9                  ; e = yes, always expedite
  2233.         cmp     ah,flowoff              ; ditto for flow off
  2234.         je      outch9
  2235.         cmp     ttyact,0                ; are we in Connect mode?
  2236.         je      outch10                 ; e = no, wait for more before sending
  2237. outch9: cmp     clone, 'U'              ; check for UB port      [ohl]
  2238.         je      outch12                 ; e = yes                [ohl]
  2239.         call    send                    ; NetBios network send routine
  2240.         jc      outch11                 ; c = error
  2241. outch10:jmp     rskp                    ; good  exit
  2242. outch11:ret                             ; bad   exit
  2243.  
  2244. outch12:call    ubsend                  ; UB network send        [ohl]
  2245.         jmp     rskp                    ; good exit              [ohl]
  2246. OUTCHR  ENDP
  2247.  
  2248. ; Network Send packet routine. Send xmt scb with no-wait option. Waits
  2249. ; up to 6 seconds for current Send to complete before emitting new Send.
  2250. ; Failure to Send resets serial port (Server mode allows reiniting of serial
  2251. ; port). Returns carry clear for success, carry set for failure.
  2252. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  2253. SEND    PROC    NEAR                    ; Network. Send session packet
  2254.         cmp     pcnet,1                 ; network ready yet?
  2255.         ja      send0b                  ; a = net is operational
  2256.         je      send0c                  ; e = net but no session, fail
  2257.         jmp     send3a                  ; no net, fail
  2258. send0c: jmp     send3                   ; net but no session
  2259. send0b: cmp     sposted,0               ; is a send outstanding now?
  2260.         je      send1                   ; e = no, go ahead
  2261.         push    cx                      ; Timed test for old send being done
  2262.         mov     ch,trans.rtime          ; receive timeout other side wants
  2263.         mov     cl,80h                  ; plus half a second
  2264.         shl     cx,1                    ; sending timeout * 512
  2265. send0:  cmp     sposted,0               ; is a send outstanding now?
  2266.         je      send0a                  ; e = no, clean up and do send
  2267.         push    cx                      ; save cx
  2268.         push    ax                      ; and ax
  2269.         mov     ax,2                    ; wait 2 milliseconds
  2270.         call    pcwait                  ;  between retests
  2271.         pop     ax
  2272.         pop     cx                      ; loop counter
  2273.         loop    send0                   ; repeat test
  2274.         pop     cx                      ; recover cx
  2275.         jmp     send3a                  ; get here on timeout, can't send
  2276. send0a: pop     cx                      ; recover cx and proceed to send
  2277.  
  2278. send1:  cmp     xmtcnt,0                ; number of items to send
  2279.         jne     send1a                  ; ne = some
  2280.         clc                             ; else don't send null packets
  2281.         ret
  2282. send1a: push    bx                      ; save bx
  2283.         mov     bx,xmtcnt               ; buffer length
  2284.         mov     xmt.scb_length,bx       ; tell buffer length
  2285.         push    cx
  2286.         push    si
  2287.         push    di
  2288.         push    es
  2289.         push    ds
  2290.         pop     es                      ; set es to datas segment
  2291.         mov     si,offset xmtbufx       ; external buffer
  2292.         mov     di,offset xmtbuf        ; copy for network packets
  2293.         mov     cx,bx                   ; buffer length
  2294.         shr     cx,1                    ; divide by two (words), set carry
  2295.         jnc     send2                   ; nc = even number of bytes
  2296.         movsb                           ; do single move
  2297. send2:  cmp     cx,0
  2298.         jle     send2a                  ; le = none to do
  2299.         rep     movsw                   ; copy the data
  2300. send2a: pop     es
  2301.         pop     di
  2302.         pop     si
  2303.         pop     cx
  2304.         mov     xmtcnt,0                ; say xmtbufx is available again
  2305.         mov     xmt.scb_cmd,nsend+nowait ; send, don't wait for completion
  2306.         mov     sposted,1               ; say send posted
  2307.         mov     bx,offset xmt           ; set pointer to scb
  2308.         call    session
  2309.         pop     bx                      ; recover pointer to scb
  2310.                                         ; success or failure?
  2311.         cmp     xmt.scb_err,0           ; good return?
  2312.         je      send4                   ; e = yes
  2313.         cmp     xmt.scb_err,npending    ; pending?
  2314.         je      send4                   ; e = yes
  2315.         cmp     xmt.scb_err,18h         ; session ended abnormally?
  2316.         jbe     send3                   ; e = yes, b = other normal errors
  2317.         push    ax
  2318.         push    dx                      ; another kind of error, show message
  2319.         mov     ah,prstr
  2320.         mov     dx,offset sndmsg        ; say send failed
  2321.         int     dos
  2322.         mov     al,xmt.scb_err          ; show error code (hex)
  2323.         call    hexout
  2324.         pop     dx
  2325.         pop     ax
  2326.                                         ; Error return
  2327. send3:  mov     pcnet,1                 ; say session is broken
  2328.         call    serrst                  ; reset serial port
  2329.         test    flags.remflg,dserver    ; server mode?
  2330.         jz      send3a                  ; z = no
  2331.         call    nethangup               ; Server: purge old NAKs etc
  2332. send3a: call    serini                  ; reinitialize it for new session
  2333.         stc                             ; set carry for failure to send
  2334.         ret
  2335. send4:  clc
  2336.         ret
  2337. SEND    ENDP
  2338.  
  2339. ; Network Send packet completion interrupt routine. At entry CS is our
  2340. ; code segment, es:bx points to scb, netbios stack, interrupts are off.
  2341. SPOST   PROC    NEAR                    ; post routine for Send packets
  2342.         push    ds
  2343.         push    ax
  2344.         mov     ax,datas
  2345.         mov     ds,ax
  2346.         mov     sposted,0               ; clear send interlock
  2347.         pop     ax
  2348.         pop     ds
  2349.         iret
  2350. SPOST   ENDP
  2351.  
  2352. ; Ungermann-Bass NETCI port send packet routine. [ohl] +++
  2353. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  2354. ubsend  proc    near
  2355.         push    ax
  2356.         push    bx
  2357.         push    cx
  2358.         push    es
  2359.         mov     cx, xmtcnt              ; number of chars                [ohl]
  2360.         jcxz    ubsend1                 ; dont send zero chars           [ohl]
  2361.         mov     bx, offset xmtbufx      ; buffer address in es:bx        [ohl]
  2362.         mov     ax, datas
  2363.         mov     es, ax
  2364. ubsend2:
  2365.         mov     ax, nciwrit             ; write function, port 0         [ohl]
  2366.         int     netci
  2367.         cmp     cx,xmtcnt               ; check that all characters sent [ohl]
  2368.         je      ubsend1                 ; e = yes                        [ohl]
  2369.         add     bx, cx                  ; point to remaining chars       [ohl]
  2370.         sub     xmtcnt,cx               ; count of remaining characters  [ohl]
  2371.         mov     cx,xmtcnt               ; need count in cx too
  2372.         jmp     short   ubsend2         ; try again to send              [ohl]
  2373. ubsend1:mov     xmtcnt,0
  2374.         pop     es
  2375.         pop     cx
  2376.         pop     bx
  2377.         pop     ax
  2378.         ret
  2379. ubsend  endp                            ;  [ohl] ---
  2380.  
  2381.  
  2382. ; dispatch prebuilt network session scb, enter with bx pointing to scb.
  2383. ; returns status in al (and ah too). Allows STARLAN Int 2ah for netint.
  2384. SESSION PROC    NEAR
  2385.         push    es                      ; save es around call
  2386.         push    ds
  2387.         pop     es                      ; make es:bx point to scb in datas seg
  2388.         mov     ax,exnbios              ; funct 4 execute netbios, for Int 2ah
  2389.         int     netint                  ; use network interrupt
  2390.         pop     es                      ; saved registers
  2391.         ret                             ; exit with status in ax
  2392. SESSION ENDP
  2393.  
  2394. ; Make a virtual circuit Session, given preset scb's from proc chknet.
  2395. ; For Server mode, does a Listen to '*', otherwise does a Call to indicated
  2396. ; remote node. Updates vcid number in scb's. Shows success or fail msg.
  2397. ; Updates network status byte pcnet to 2 if session is established.
  2398. ; Does nothing if a session is active upon entry; otherwise, does a network
  2399. ; hangup first to clear old session material from adapter board. This is
  2400. ; the second procedure to call in initializing the network for usage.
  2401. SETNET  PROC    NEAR                    ; Network, make a connection
  2402.         cmp     lposted,1               ; Listen pending?
  2403.         je      setne0                  ; e = yes, exit now
  2404.         cmp     pcnet,1                 ; session active?
  2405.         jbe     setne1                  ; be = no
  2406. setne0: ret
  2407.                                         ; No Session
  2408. setne1: call    nethangup               ; clear old session material
  2409.         test    flags.remflg,dserver    ; Server mode?
  2410.         jz      setne2                  ; z = no, file xfer or Connect
  2411.                                         ; Server mode, post a Listen (async)
  2412.         mov     lsn.scb_rname,'*'       ; accept anyone
  2413.         mov     ax,500
  2414.         call    pcwait                  ; 0.5 sec wait
  2415.         push    bx
  2416.         mov     lposted,1               ; set listen interlock flag
  2417.         mov     lsn.scb_cmd,nlisten+nowait ; do LISTEN command, no wait
  2418.         mov     bx,offset lsn
  2419.         call    session
  2420.         pop     bx
  2421.         ret
  2422. setne2:                                 ; Non-server (Client) mode
  2423.         push    bx                      ; save reg
  2424.         test    nettype,starlan         ; STARLAN?
  2425.         jz      setne2a                 ; z = no
  2426.         cmp     xmt.scb_vrlen,0         ; yes, using long name support?
  2427.         je      setne2a                 ; e = no
  2428.         push    es                      ; save reg
  2429.         push    ds
  2430.         pop     es                      ; make es:bx point to xmt scb
  2431.         mov     bx,offset xmt           ; use xmt scb for the call
  2432.         mov     xmt.scb_cmd,ncall       ; CALL_ISN, vrname + vrlen are ready
  2433.         int     5bh                     ; STARLAN CALL Int 5bh, wait
  2434.         pop     es                      ; restore regs
  2435.         pop     bx
  2436.         jmp     short setne3            ; finish up
  2437.  
  2438. setne2a:                                ; Regular Netbios Call
  2439.         mov     xmt.scb_cmd,ncall       ; CALL, wait for answer
  2440.         mov     bx,offset xmt           ; setup scb pointer
  2441.         call    session
  2442.         pop     bx                      ; restore register
  2443.  
  2444. setne3: push    dx                      ; common Call completion, show status
  2445.         test    xmt.scb_err,0ffh        ; is there a non-zero return code?
  2446.         jnz     setne3a                 ; nz = yes, do bad return
  2447.         or      al,al                   ; check error return
  2448.         jnz     setne3a                 ; nz = bad connection
  2449.         jmp     short setne4            ; good connection so far
  2450. setne3a:mov     dx,offset nbadset       ; say can't reach remote node
  2451.         mov     ah,prstr
  2452.         int     dos
  2453.         call    saynode                 ; show remote host node name
  2454.         jmp     setne4c
  2455.                                         ; keep results of Call (vcid)
  2456. setne4: mov     al,xmt.scb_vcid         ; local session number
  2457.         mov     rcv.scb_vcid,al         ; for receiver too
  2458.         mov     can.scb_vcid,al         ; for sending Breaks
  2459.         mov     pcnet,2                 ; say session has started
  2460.         test    flags.remflg,dregular+dquiet ; regular or quiet display?
  2461.         jnz     setne4c                 ; nz = yes, show only no-connect msg
  2462.         mov     dx,offset ngodset       ; say good connection
  2463.         mov     ah,prstr
  2464.         int     dos
  2465.         call    saynode                 ; show remote host name
  2466. setne4c:pop     dx
  2467.         cmp     pcnet,1                 ; check connection again
  2468.         ja      setne5                  ; a = good so far
  2469.         stc                             ; set carry for failure
  2470.         ret
  2471. setne5: clc                             ; carry clear for success
  2472.         ret
  2473. SETNET  ENDP
  2474.  
  2475. saynode proc    near            ; display node name on screen, si=name ptr
  2476.         push    ax
  2477.         push    cx
  2478.         push    dx
  2479.         push    si
  2480.         mov     ah,conout
  2481.         mov     si,offset nambuf        ; remote node string
  2482.         mov     cx,64                   ; up to 64 bytes long
  2483. saynod1:cld
  2484.         lodsb                           ; get remote node name char into al
  2485.         mov     dl,al
  2486.         int     dos                     ; display it
  2487.         cmp     al,' '                  ; was it a space?
  2488.         jbe     saynod2                 ; be = yes, quit here
  2489.         loop    saynod1                 ; do all 16 chars
  2490. saynod2:mov     ah,prstr
  2491.         mov     dx,offset crlf
  2492.         int     dos
  2493.         pop     si
  2494.         pop     cx
  2495.         pop     cx
  2496.         pop     ax
  2497.         ret
  2498. saynode endp
  2499.  
  2500. LPOST   PROC    FAR             ; Interrupt Post routine for Listen call
  2501.         push    ds              ; update vcid and calling node name in scb's
  2502.         push    cx
  2503.         push    es
  2504.         push    si
  2505.         push    di
  2506.         mov     cx,datas                ; reestablish datas segment
  2507.         mov     ds,cx
  2508.         mov     es,cx
  2509.         mov     si,offset lsn.scb_rname ; copy remote name to rcv and xmt scbs
  2510.         push    si
  2511.         mov     di,offset rcv.scb_rname
  2512.         mov     cx,8                    ; 16 byte field
  2513.         cld
  2514.         rep     movsw
  2515.         mov     cx,8
  2516.         pop     si
  2517.         push    si
  2518.         mov     di,offset xmt.scb_rname
  2519.         rep     movsw
  2520.         mov     cx,8
  2521.         pop     si
  2522.         mov     di,offset nambuf        ; and to nambuf for display
  2523.         rep     movsw
  2524.         mov     cl,lsn.scb_vcid         ; local session number
  2525.         mov     rcv.scb_vcid,cl
  2526.         mov     xmt.scb_vcid,cl
  2527.         mov     can.scb_vcid,cl
  2528.         mov     lposted,0               ; clear interlock flag
  2529.         mov     pcnet,2                 ; say net ready due to a Listen
  2530.         pop     di
  2531.         pop     si
  2532.         pop     es
  2533.         pop     cx
  2534.         pop     ds
  2535.         iret                            ; return from interrupt
  2536. LPOST   ENDP
  2537.  
  2538.  
  2539. NETHANGUP PROC  NEAR                 ; disconnect network session, keep names
  2540.         cmp     pcnet,0                 ; network started?
  2541.         je      nethang1                ; e = no
  2542.         cmp     clone, 'U'              ; Ungermann-Bass port? [ohl]
  2543.         je      nethang2                ; e = yes [ohl]
  2544.         push    bx                      ; NetBios network
  2545.         mov     bx,offset can
  2546.         mov     can.scb_cmd,ncancel     ; set cancel op code
  2547.         mov     can.scb_baddr,offset lsn ; cancel listens
  2548.         mov     lposted,0               ; say no listen
  2549.         call    session
  2550.         mov     can.scb_baddr,offset rcv ; cancel receives
  2551.         call    session
  2552.         mov     rposted,0               ; say no receives posted
  2553.         mov     can.scb_baddr,offset xmt ; cancel sends
  2554.         call    session
  2555.         mov     sposted,0               ; say no sends posted
  2556.         mov     xmtcnt,0                ; reset output buffer counter
  2557.         mov     xmt.scb_cmd,nhangup     ; hangup, and wait for completion
  2558.         mov     bx,offset xmt
  2559.         call    session
  2560.         pop     bx
  2561.         mov     pcnet,1                 ; say network but no session
  2562.         call    serrst                  ; reset the serial port for reiniting
  2563. nethang1:ret
  2564.                                         ; UB network [ohl] +++
  2565. nethang2:call   ubclose                 ; close connection if any [ohl]
  2566.         mov     xmtcnt,0
  2567.         mov     pcnet,1
  2568.         ret                             ;  [ohl] ---
  2569. NETHANGUP ENDP
  2570.  
  2571. ; Ungermann Bass. Do a disconnect from the current connection.
  2572. ubclose proc    near
  2573.         push    ax
  2574.         push    cx
  2575.         cmp     nettype,netone          ; UB network has been activated?
  2576.         jz      ubclos1                 ; z = no
  2577.         mov     ax, ncistat             ; get status                     [ohl]
  2578.         int     netci
  2579.         cmp     ch, 1                   ; check if we have a connection  [ohl]
  2580.         jne     ubclos1                 ; ne = no                        [ohl]
  2581.         mov     ax, ncicont             ; control function               [ohl]
  2582.         mov     cx, ncidis              ; say disconnect                 [ohl]
  2583.         int     netci
  2584. ubclos2:call    ubrecv                  ; read response from net cmdintpr[ohl]
  2585.         jnc     ubclos2                 ; continue till no chars         [ohl]
  2586. ubclos1:and     nettype,not netone      ; remove network type
  2587.         mov     pcnet,0                 ; say no network
  2588.         pop     cx
  2589.         pop     dx
  2590.         ret
  2591. ubclose endp
  2592.  
  2593. ; Called when Kermit exits. Name passed to mssker by proc chknet
  2594. ; in word lclexit.
  2595. NETCLOSE PROC   NEAR                    ; close entire network connection
  2596.         cmp     pcnet,0                 ; network ever used?
  2597.         je      netclo1                 ; e = no, so don't touch it
  2598.         call    nethangup               ; close connections
  2599.         test    nettype,netbios         ; NetBios activated?
  2600.         jz      netclo1                 ; z = no
  2601.         push    bx
  2602.         mov     bx,offset xmt
  2603.         mov     xmt.scb_cmd,ndelete     ; delete our local Kermit name
  2604.         call    session                 ;  from net adapter board
  2605.         pop     bx
  2606.         mov     pcnet,0                 ; say no network
  2607.         and     nettype,not netbios     ; remove network kind
  2608. netclo1:ret
  2609. NETCLOSE ENDP
  2610.  
  2611. ; Start connection process to network. Obtains Network board local name
  2612. ; and appends '.K' to form Kermit's local name (removed when Kermit exits).
  2613. ; If no local name is present then use name 'mskermit.K'.
  2614. ; Sets local name in scb's for xmt, rcv, lsn. (Does not need DOS 3.x)
  2615. ; Sets NETDONE pointer to procedure netclose for Kermit exit.
  2616. ; Verifies existance of interrupt 5ch support, verifies vendor specific
  2617. ; support for BREAK and other features, sets network type bit in nettype,
  2618. ; sets BREAK support in nsbrk, hangsup old session if new node name given,
  2619. ; fills in local and remote node names and name number in scbs (including ISN
  2620. ; names for STARLAN), and sets network status byte pcnet to 0 (no net) or
  2621. ; to 1 (net ready). This is the first procedure called to init network usage.
  2622. ; Byte count of new host name is in temp from COMS.
  2623. chknet  proc    near
  2624.         cmp     clone,'U'               ; Ungermann Bass network?
  2625.         jne     chknea                  ; ne = no
  2626.         mov     pcnet,0                 ; force reactivation of UB net
  2627. chknea: cmp     pcnet,2                 ; session active now?
  2628.         jb      chknec                  ; b = no
  2629.         cmp     temp,0                  ; byte count of new name, if any
  2630.         je      chkneb                  ; e = none, resume old session
  2631.         mov     dx,offset naskpmt       ; prompt for New or Resume
  2632.         call    prompt
  2633.         mov     dx,offset nettab        ; table of answers
  2634.         mov     bx,0                    ; help for the question
  2635.         mov     ah,cmkey                ; get answer keyword
  2636.         call    comnd
  2637.          jmp r                          ; failed
  2638.          nop
  2639.         mov     rdbuf,bl                ; save keyword action value here
  2640.         mov     ah,cmcfm                ; get a confirm
  2641.         call    comnd
  2642.          jmp    r                       ; no confirm
  2643.          nop
  2644.         cmp     rdbuf,0                 ; New session?
  2645.         je      chkneb                  ; e = yes
  2646.         clc
  2647.         ret                             ; resume old one
  2648. chkneb: jmp     chknet1                 ; skip presence tests
  2649.  
  2650. chknec:                         ; setup addresses and clear junk in scb's
  2651.         cmp     pcnet,0                 ; have we been here already?
  2652.         je      chkned                  ; e = no
  2653.         jmp     chknet1                 ; yes, skip init part
  2654. chkned: mov     xmtcnt,0                ; say buffer is empty
  2655.         mov     nsbrk,0                 ; assume no BREAK across network
  2656.         and     nettype,not netbios     ; say no NetBios network yet
  2657.  
  2658.         push    bx
  2659.         push    es                      ; Test for Netbios presence, IBM way
  2660.         mov     ah,35h                  ; DOS get interrupt vector
  2661.         mov     al,netint               ; the netbios vector
  2662.         int     dos                     ; returns vector in es:bx
  2663.         mov     ax,es
  2664.         cmp     ax,0f000h               ; rom bios segment??
  2665.         jb      chknee                  ; b = not likely, else Bios has
  2666.         mov     ax,0                    ;  trapped this vector to dummy iret
  2667.         mov     bx,0                    ; fake null vector
  2668. chknee: or      bx,ax                   ; is vector present?
  2669.         pop     es
  2670.         pop     bx
  2671.         jz      chknet0                 ; z = no
  2672.         mov     xmt.scb_cmd,7fh ; presence test, 7fh is illegal command code
  2673.         mov     xmt.scb_err,0           ; clear response field
  2674.         push    bx
  2675.         mov     bx,offset xmt           ; address of the session control block
  2676.         call    session                 ; execute operation
  2677.         pop     bx
  2678.         mov     al,xmt.scb_err          ; get response
  2679.         cmp     xmt.scb_err,3       ; 'illegal function', so adapter is ready
  2680.         jne     chknet0                 ; ne = failure
  2681.         push    bx
  2682.         push    es                      ; Test for Netbios presence, IBM way
  2683.         mov     ah,35h                  ; DOS get interrupt vector
  2684.         mov     al,2ah                  ; the netbios vector 2ah
  2685.         int     dos                     ; returns vector in es:bx
  2686.         mov     ax,es
  2687.         cmp     ax,0f000h               ; rom bios segment??
  2688.         jb      chknef                  ; b = not likely
  2689.         mov     ax,0
  2690.         mov     bx,0                    ; fake null vector
  2691. chknef: or      bx,ax                   ; is vector present?
  2692.         pop     es
  2693.         pop     bx
  2694.         jz      chknet0                 ; z = no, no NetBios network
  2695.         or      nettype,netbios         ; say have NetBios network
  2696.                                 ; AT&T STARLAN board check (0ddh=magic #)
  2697.         mov     ah,0                    ; vendor installation check on int 2ah
  2698.         mov     al,0                    ; do error retry
  2699.         int     2ah                     ; session level interrupt
  2700.         cmp     ah,0ddh                 ; 0ddh = magic number, success?
  2701.         jne     chknet1                 ; ne = no
  2702.         or      nettype,starlan         ; say using STARLAN, have int 2ah
  2703.         push    bx
  2704.         push    es                      ; Test for vector
  2705.         mov     ah,35h                  ; DOS get interrupt vector
  2706.         mov     al,5bh                  ; 5bh = STARLAN netbios ext'd vector
  2707.         int     dos                     ; returns vector in es:bx
  2708.         mov     ax,es
  2709.         or      bx,ax                   ; is vector present?
  2710.         pop     es
  2711.         pop     bx
  2712.         jz      chknet1                 ; z = no
  2713.         mov     nsbrk,1                 ; network BREAK supported
  2714.         jmp     chknet1
  2715.  
  2716. chknet0:mov     pcnet,0                 ; no network yet
  2717.         push    ax
  2718.         push    dx
  2719.         mov     ah,prstr
  2720.         mov     dx,offset nonetmsg      ; say network is not available
  2721.         int     dos
  2722.         pop     dx
  2723.         pop     ax
  2724.         stc                             ; set carry for failure
  2725.         ret                             ; and exit now
  2726.  
  2727.                                         ; net ready to operate
  2728. chknet1:cmp     temp,0                  ; byte count of new name, from COMS
  2729.         jne     chkne1e                 ; ne = new name given
  2730.         jmp     chknet2                 ; nothing, so leave names intact
  2731. chkne1e:cmp     pcnet,2                 ; is session active now?
  2732.         jb      chkne1d                 ; b = no
  2733.         call    nethangup               ; hangup net to clear old connection
  2734. chkne1d:                                ; start fresh connection
  2735.         push    si
  2736.         push    di
  2737.         push    es
  2738.         push    ds
  2739.         pop     es                      ; make es:di point to datas segment
  2740.         cld
  2741.         mov     cx,8                    ; 16 bytes for a node name
  2742.         mov     ax,'  '                 ; first, fill with spaces
  2743.         mov     di,offset xmt.scb_rname ; remote name field, clear it
  2744.         rep     stosw
  2745.         test    nettype,starlan         ; STARLAN?
  2746.         jz      chkne1b                 ; z = no
  2747.                                         ; begin STARLAN section
  2748.         mov     xmt.scb_vrname,0        ; STARLAN var length name ptr
  2749.         mov     xmt.scb_vrname+2,0      ; segement of name
  2750.         mov     xmt.scb_vrlen,0         ; and its length
  2751.         mov     cx,temp                 ; count of characters in new name
  2752.         cmp     cx,16                   ; > 16 chars in remote node name?
  2753.         ja      chkne1a                 ; a = yes, too long for Netbios
  2754.         mov     al,'/'                  ; scan for slashes in name
  2755.         mov     di,offset nambuf        ; source of text
  2756.         push    es                      ; save es around scan
  2757.         push    ds
  2758.         pop     es                      ; point es at datas segment
  2759.         cld
  2760.         repne   scasb                   ; look for the slash
  2761.         pop     es
  2762.         jne     chkne1b         ; ne = none, do regular Netbios name storage
  2763. chkne1a:                                ; STARLAN ISN long remote name support
  2764.         mov     xmt.scb_vrname,offset nambuf    ; STARLAN var length name ptr
  2765.         mov     xmt.scb_vrname+2,datas          ; segment of remote name
  2766.         mov     cx,temp                 ; get name length again (in cl)
  2767.         mov     xmt.scb_vrlen,cl        ; indicate its length
  2768.         jmp     chkne1c                 ; copy blanks in remote name field
  2769.                                         ; end STARLAN section
  2770.  
  2771. chkne1b:mov     cx,temp                 ; Regular Netbios form, name length
  2772.         mov     si,offset nambuf        ; source of text
  2773.         mov     di,offset xmt.scb_rname ; destination is remote name
  2774.         rep     movsb                   ; copy text to transmitter's scb
  2775.         mov     cx,16
  2776. chkne1c:mov     cx,8                    ; 8 words
  2777.         mov     si,offset xmt.scb_rname ; from here
  2778.         mov     di,offset rcv.scb_rname ; to receiver's scb also
  2779.         rep     movsw
  2780.         pop     es
  2781.         pop     di
  2782.         pop     si
  2783.  
  2784. chknet2:cmp     pcnet,0                 ; started net?
  2785.         je      chknet2c                ; e = no
  2786.         ret                             ; else quit here
  2787. chknet2c:
  2788.         mov     ah,prstr
  2789.         mov     dx,offset netmsg1       ; say checking node name
  2790.         int     dos
  2791.         push    word ptr xmt.scb_rname  ; save first two bytes (user spec)
  2792.         mov     byte ptr xmt.scb_rname,'*'      ; call to local name
  2793.         push    bx
  2794.         mov     xmt.scb_cmd,naustat     ; get Network Adapter Unit status
  2795.         mov     bx,offset xmt
  2796.         call    session
  2797.         pop     bx
  2798.         pop     word ptr xmt.scb_rname  ; restore remote name first two bytes
  2799. chknet2a:
  2800.         push    es                      ; save registers
  2801.         push    di
  2802.         push    si
  2803.         push    cx
  2804.         push    ds
  2805.         pop     es                      ; set es:di to datas segment
  2806.         mov     si,offset xmtbuf+60 ; where local name is returned (1st entry)
  2807.         cmp     word ptr xmtbuf+58,0    ; is local name empty?
  2808.         jne     chknet2b                ; ne = no, use name from table
  2809.         mov     si,offset deflname      ; else use default local name
  2810. chknet2b:
  2811.         mov     di,offset xmt.scb_lname ; where to put it in scb
  2812.         mov     cx,14                   ; 16 bytes minus extension of '.K'
  2813.         cld                             ; append extension of '.K' to loc name
  2814. chknet3:cmp     byte ptr[si],' ' ; find first space (end of regular node name)
  2815.         jbe     chknet4                 ; be = found one (or control code)
  2816.         movsb                           ; copy local name to scb
  2817.         loop    chknet3                 ; continue though local name
  2818. chknet4:cmp     word ptr [di-2],'K.'    ; is extension '.K' present already?
  2819.         je      chknet4a;;;5                    ; e = yes, nothing to add
  2820.         cmp     word ptr [di-2],'k.'    ; check lower case too
  2821.         je      chknet4a;;;5                    ; e = yes, nothing to add
  2822.         mov     word ptr [di],'K.'      ; append our extension of '.K'
  2823.         add     di,2                    ; step over our new extension
  2824.         sub     cx,2
  2825.                                         ; complete field with spaces
  2826.         add     cx,2                    ; 15th and 16th chars
  2827. chknet4a:jcxz   chknet5                 ; z = nothing to add
  2828.         mov     al,' '                  ; space as padding
  2829.         rep     stosb
  2830. chknet5:mov     si,offset xmt.scb_lname
  2831.         mov     di,offset rcv.scb_lname ; put in receiver scb too
  2832.         mov     cx,8
  2833.         rep     movsw
  2834.         mov     cx,8
  2835.         mov     si,offset xmt.scb_lname
  2836.         mov     di,offset lsn.scb_lname ; in Listen scb also
  2837.         rep     movsw
  2838.         pop     cx
  2839.         pop     si
  2840.         pop     di
  2841.         pop     es
  2842. chknet6:
  2843.         push    bx                      ; Put our new local name in NAU
  2844.         mov     xmt.scb_cmd,nadd        ; ADD NAME, wait
  2845.         mov     bx,offset xmt
  2846.         call    session
  2847.         pop     bx
  2848.         mov     al,xmt.scb_err          ; get error code
  2849.         cmp     al,0                    ; success?
  2850.         je      chknet7                 ; e = yes
  2851.         cmp     al,0dh                  ; duplicate name in local table?
  2852.         je      chknet6a                ; e = yes
  2853.         cmp     al,16h                  ; name used elsewhere?
  2854.         je      chknet6a                ; e = yes
  2855.         cmp     al,19h                  ; name conflict?
  2856.         je      chknet6a                ; e = yes
  2857.         push    ax
  2858.         mov     ah,prstr                ; another kind of error
  2859.         mov     dx,offset chkmsg1       ; say can't construct local name
  2860.         int     dos
  2861.         pop     ax
  2862.         call    hexout                  ; display it (in al)
  2863.         mov     ah,prstr
  2864.         mov     dx,offset crlf
  2865.         int     dos
  2866.         mov     pcnet,0                 ; say no connection today
  2867.         stc                             ; set carry for failure
  2868.         ret
  2869. chknet6a:
  2870.         mov     ah,prstr                ; ask for another name
  2871.         mov     dx,offset chkmsg2       ; prompt message
  2872.         int     dos
  2873.         mov     ah,conout               ; show name itself
  2874.         push    cx
  2875.         mov     cx,16                   ; 16 bytes in name field
  2876.         mov     si,offset xmt.scb_lname
  2877. chknet6c:
  2878.         lodsb                           ; get name char into al
  2879.         mov     dl,al
  2880.         int     dos
  2881.         mov     byte ptr[si-1],' '      ; clear old name as we go
  2882.         loop    chknet6c
  2883.         pop     cx
  2884.         mov     ah,prstr
  2885.         mov     dx,offset chkmsg3       ; rest of prompt
  2886.         int     dos
  2887.  
  2888.         mov     ah,0ah                  ; read buffered line from stdin
  2889.         mov     dx,offset xmtbuf+58     ; where to put text (xmtbuf+60=text)
  2890.         mov     xmtbuf+58,15            ; buf capacity, including cr at end
  2891.         mov     xmtbuf+59,0             ; say text in buffer = none
  2892.         int     dos
  2893.         jc      chknet6b                ; c = error
  2894.         cmp     xmtbuf+59,0             ; any bytes read?
  2895.         je      chknet6b                ; e = no, exit failure
  2896.         mov     ah,prstr                ; say rechecking name
  2897.         mov     dx,offset netmsg1
  2898.         int     dos
  2899.         jmp     chknet2a                ; go reinterpret name
  2900. chknet6b:
  2901.         stc                             ; set carry for failure
  2902.         ret
  2903.  
  2904. chknet7:mov     pcnet,1                 ; network is present (but not active)
  2905.         mov     al,xmt.scb_num          ; name number
  2906.         mov     rcv.scb_num,al
  2907.         mov     lsn.scb_num,al
  2908.         mov     lclexit,offset netclose ; address to close network
  2909.         push    ax
  2910.         push    cx
  2911.         push    dx
  2912.         mov     dx,offset netmsg2        ; say net going
  2913.         mov     ah,prstr
  2914.         int     dos
  2915.         mov     si,offset rcv.scb_lname ; display our local name
  2916.         mov     ah,conout
  2917.         mov     cx,16
  2918.         cld
  2919. chknet9:lodsb                           ; byte from si to al
  2920.         mov     dl,al
  2921.         int     dos                     ; display it
  2922.         loop    chknet9
  2923.         mov     ah,prstr
  2924.         mov     dx,offset crlf          ; add cr/lf
  2925.         int     dos
  2926.         pop     dx
  2927.         pop     cx
  2928.         pop     ax
  2929.         clc                             ; carry clear for success
  2930.         ret
  2931. chknet  endp
  2932.  
  2933. ;                                       ; [ohl] ++++
  2934. ; Verifies existance of interrupt 6Bh support, verifies vendor specific
  2935. ; support for BREAK and other features, sets network type bit in nettype,
  2936. ; sets BREAK support in nsbrk and sets network status byte pcnet to 0
  2937. ; (no net) or to 1 (net ready). This is the first procedure called to
  2938. ; init Ungermann-Bass NETCI terminal port network usage.
  2939. chkub  proc    near
  2940.         push    bx
  2941.         push    es                      ; Test for vector
  2942.         mov     ah,35h                  ; DOS get interrupt vector
  2943.         mov     al,6bh                  ; 6bh = Net/One command interpreter
  2944.                                         ;  interface, with break support
  2945.         int     dos                     ; returns vector in es:bx
  2946.         mov     ax,es                   ; is vector in rom bios??? [jrd]
  2947.         cmp     ax,0f000h               ; rom bios starts here
  2948.         jb      chkub2                  ; b = not likely
  2949.         mov     ax,0                    ; yes, say no network
  2950.         mov     es,ax                   ; fake a null vector
  2951.         mov     bx,ax
  2952. chkub2: mov     ax,es
  2953.         or      bx,ax                   ; is vector present?
  2954.         jz      chkub0                  ; z = no
  2955.         mov     al,0ffh                 ; test value (anything non-zero)
  2956.         mov     ah,2                    ; function code for testing net board
  2957.         int     netci
  2958.         or      al,al                   ; al = 0 means board is ok
  2959.         jnz     chkub0                  ; nz = not ok
  2960.         pop     es
  2961.         pop     bx
  2962.         mov     nsbrk,1                 ; network BREAK supported
  2963.         or      nettype,netone          ; say have Net/One
  2964.         clc                             ; return success
  2965.         ret
  2966.  
  2967. chkub0: pop     es                      ; clean stack from above
  2968.         pop     bx
  2969.         push    ax
  2970.         push    dx
  2971.         mov     ah,prstr
  2972.         mov     dx,offset nonetmsg      ; say network is not available
  2973.         int     dos
  2974.         pop     dx
  2975.         pop     ax
  2976.         stc                             ; set carry for failure
  2977.         ret                             ; and exit now
  2978. chkub  endp                             ; [ohl] ----
  2979.  
  2980. hexout  proc    near                    ; display byte in al as hex value
  2981.         push    ax                      ; all regs preserved
  2982.         push    cx
  2983.         push    dx
  2984.         mov     cx,2                    ; two nibbles
  2985. hexout1:push    cx                      ; save counter
  2986.         mov     cl,4                    ; high nibble
  2987.         ror     al,cl                   ; put in low order field
  2988.         mov     dl,al
  2989.         xchg    ch,al                   ; save al byte in ch
  2990.         and     dl,0fh                  ; four bits
  2991.         cmp     dl,9                    ; too big?
  2992.         jbe     hexout2                 ; be = no
  2993.         add     dl,'A'-'9'-1            ; bump up to A-F
  2994. hexout2:add     dl,'0'
  2995.         mov     ah,conout
  2996.         int     dos
  2997.         xchg    ch,al                   ; recover data byte
  2998.         pop     cx
  2999.         loop    hexout1                 ; do second nibble
  3000.         mov     dl,'H'                  ; add a final hex ident
  3001.         int     dos
  3002.         pop     ax
  3003.         pop     cx
  3004.         pop     dx
  3005.         ret
  3006. hexout  endp
  3007.  
  3008. ; local routine to see if we have to transmit an xon
  3009. chkxon  proc    near
  3010.         cmp     flowon,0                ; doing flow control?
  3011.         je      chkxo1                  ; no, skip all this
  3012.         test    xofsnt,usron            ; did user send an xoff?
  3013.         jnz     chkxo1                  ; nz = yes, don't contradict it here
  3014.         test    xofsnt,bufon            ; have we sent a buffer level xoff?
  3015.         jz      chkxo1                  ; z = no, forget it
  3016.         cmp     count,mntrgl            ; below (low water mark) trigger?
  3017.         jae     chkxo1                  ; no, forget it
  3018.         mov     ah,flowon               ; ah gets xon
  3019.         and     xofsnt,off              ; remember we've sent the xon
  3020.         call    outch2              ; send via non-flow controlled entry point
  3021.          nop
  3022.          nop
  3023.          nop                            ; in case it skips
  3024. chkxo1: ret
  3025. chkxon  endp
  3026.  
  3027. ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
  3028. ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
  3029. ; else repeat cycle. Requires that the port be initialized before hand.
  3030. ; Ihosts is used by the local send-file routine just after initializing
  3031. ; the serial port.
  3032. ; 22 March 1986 [jrd]
  3033. ; 22 June 1986 Don't send null char if not using flow control. [jrd]
  3034.  
  3035. IHOSTS  PROC    NEAR
  3036.         push    ax              ; save the registers
  3037.         push    cx
  3038.         push    dx
  3039.         mov     xofrcv,off      ; clear old xoff received flag
  3040.         mov     xofsnt,off      ; and old xoff sent flag
  3041.         mov     ah,flowon       ; put Go-ahead flow control char in ah
  3042.         or      ah,ah           ; check for null char
  3043.         jz      ihosts1         ; z = null, don't send it
  3044.         call    outchr          ; send it (release Host's output queue)
  3045.          nop                    ; outchr can do skip return
  3046.          nop
  3047.          nop
  3048. ihosts1:call    clrbuf          ; clear out interrupt buffer
  3049.         pop     dx              ; empty buffer. we are done here
  3050.         pop     cx
  3051.         pop     ax
  3052.         ret
  3053. IHOSTS  ENDP
  3054.  
  3055. ; IHOSTR - initialize the remote host for our reception of a file by
  3056. ; sending the flow-on character (XON typically) to release any held
  3057. ; data. Called by receive-file code just after initializing the serial
  3058. ; port. 22 March 1986 [jrd]
  3059. ; 22 June 1986 Don't send null char if not using flow control. [jrd]
  3060. IHOSTR  PROC    NEAR
  3061.         push    ax              ; save regs
  3062.         push    cx
  3063.         mov     xofrcv,off      ; clear old xoff received flag
  3064.         mov     xofsnt,off      ; and old xoff sent flag
  3065.         mov     ah,flowon       ; put Go-ahead flow control char in ah
  3066.         or      ah,ah           ; check for null char
  3067.         jz      ihostr1         ; z = null, don't send it
  3068.         call    outchr          ; send it (release Host's output queue)
  3069.          nop                    ; outchr can do skip return
  3070.          nop
  3071.          nop
  3072. ihostr1:pop     cx
  3073.         pop     ax
  3074.         ret
  3075. IHOSTR  ENDP
  3076.  
  3077. ; Send a break out the current serial port.  Returns normally.
  3078. ; Do both regular and long Break. 6 March 1987 [jrd]
  3079.  
  3080. SENDBR  PROC    NEAR
  3081.         push    cx              ; Regular Break entry point
  3082.         mov     cx,275          ; 275 milliseconds in regular Break
  3083.         call    sendbw          ; call worker routine to do it
  3084.         pop     cx
  3085.         clc                     ; don't exit Connect mode
  3086.         ret
  3087. SENDBL: push    cx              ; Long Break entry point
  3088.         mov     cx,1800         ; 1.8 second long break
  3089.         call    sendbw          ; call worker routine to do it
  3090.         pop     cx
  3091.         clc                     ; don't exit Connect mode
  3092.         ret
  3093.                                 ; worker - send Break for cx millisec
  3094. sendbw: test    clone,0ffh      ; running on a semi-clone?
  3095.         jnz     sendbw2         ; nz = yes, can't do this via Bios
  3096.         push    ax
  3097.         push    dx
  3098.         mov     dx,brkadr       ; Port address
  3099.         in      al,dx           ; Get current setting
  3100.         push    ax              ; save setting on the stack
  3101.         or      al,brkval       ; Set send-break bit(s)
  3102.         out     dx,al           ; Start the break
  3103.         mov     ax,cx           ; # of ms to wait
  3104.         call    pcwait          ; hold break for desired interval
  3105.         pop     ax              ; restore Line Control Register
  3106.         out     dx,al           ; Stop the break
  3107.         pop     dx
  3108.         pop     ax
  3109.         ret
  3110. sendbw2:
  3111.         cmp     clone, 'U'      ; is it an UB NETCI port?                [ohl]
  3112.         je      sendbw6         ; e = yes                                [ohl]
  3113.         cmp     clone,'N'       ; is this a NetBios network port?
  3114.         jne     sendbw4         ; ne = no
  3115.         cmp     nsbrk,0         ; is network able to send a break?
  3116.         je      sendbw4         ; e = no
  3117.         test    nettype,starlan ; STARLAN: network break supported?
  3118.         jz      sendbw4         ; z = no
  3119.         push    bx
  3120.         push    es              ; save es around call
  3121.         push    ds
  3122.         pop     es              ; make es:bx point to scb in datas segment
  3123.         mov     bx,offset can   ; use Cancel control block
  3124.         mov     can.scb_cmd,netbrk ; send net Break command
  3125.         int     5bh             ; use network Break interrupt
  3126.         pop     es              ; saved registers
  3127.         pop     bx
  3128. sendbw4:ret
  3129. sendbw6:                        ; UB port send break             [ohl] +++
  3130.         push    ax
  3131.         push    cx
  3132.         mov     ax, ncicont + 0 ; call control, use 0 for network port num [ohl]
  3133.         mov     cl, ncibrk      ; request break                          [ohl]
  3134.         int     netci           ; Net/One command interface int. (6Bh)   [ohl]
  3135.         pop     cx
  3136.         pop     ax
  3137.         ret                     ;  [ohl] ---
  3138. SENDBR  ENDP
  3139.  
  3140. ; Initialization for using serial port.  This routine performs
  3141. ; any initialization necessary for using the serial port, including
  3142. ; setting up interrupt routines, setting buffer pointers, etc.
  3143. ; Doing this twice in a row should be harmless (this version checks
  3144. ; a flag and returns if initialization has already been done).
  3145. ; SERRST below should restore any interrupt vectors that this changes.
  3146. ;
  3147. ; Revised slightly by Joe R. Doupnik 22 Dec 1985 to prevent interrupts
  3148. ; being enabled until we're done, to stop interrupts from occurring when
  3149. ; TX holding buffer becomes empty (a useless interrupt for us), and to
  3150. ; shorten the time between enabling interrupts and our exit.
  3151. ; Returns carry clear if success, else carry set.
  3152. SERINI  PROC    NEAR
  3153.         call    pcwtst                  ; recalibrate pcwait loop timer
  3154.         cmp     portin,0                ; Did we initialize port already?
  3155.         jle     serin0                  ; le = no, not yet
  3156.         jmp     serin4                  ; Yes, update flow and leave
  3157. serin0: cmp     portin,-1               ; have we run SET PORT or equiv?
  3158.         jne     serin5                  ; ne = yes, continue
  3159.         mov     bl,flags.comflg         ; pass current port ident
  3160.         call    comstrt                 ; do SET PORT now
  3161.          ret                            ; failed, exit now
  3162.          nop
  3163.          nop
  3164. serin5: cmp     clone,0                 ; non-clone
  3165.         je      serin2                  ; e = yes, real thing
  3166.         jmp     serin3                  ; else use Bios. Finish initialization
  3167.  
  3168. serin2: cmp     clone,'N'               ; Network port?
  3169.         jne     serin2a                 ; ne = no
  3170.         jmp     serin3                  ; yes
  3171. serin2a:push    bx
  3172.         push    es
  3173.         in      al,21H                  ; Interrupt controller
  3174.         mov     savirq,al               ; save state here for restoration
  3175.         or      al,modem.mddis          ; Inhibit IRQ 3 or IRQ 4
  3176.         out     21H,al
  3177.         mov     al,byte ptr modem.mdintv ; desired interrupt vector
  3178.         mov     ah,35H                  ; Int 21H, function 35H = Get Vector
  3179.         int     dos                     ; get vector into es:bx
  3180.         mov     word ptr savsci,bx    ; save address offset of original vector
  3181.         mov     word ptr savsci+2,es    ;  and its segment
  3182.         mov     al,byte ptr modem.mdintv ; interrupt number for IRQ 4 or IRQ 3
  3183.         mov     dx,offset serint        ; offset of our interrupt routine
  3184.         push    ds                      ; save ds around next DOS call
  3185.         mov     bx,cs                   ; compose full address of our routine
  3186.         mov     ds,bx                   ; segment is the code segment
  3187.         mov     ah,25H                  ; set interrupt address from ds:dx
  3188.         int     dos
  3189.         pop     ds
  3190.         mov     al,rs232                ; interrupt number for Bios serial port
  3191.         mov     ah,35H                  ; get vector into es:bx
  3192.         int     dos
  3193.         mov     word ptr sav232,bx      ; save offset
  3194.         mov     word ptr sav232+2,es    ; save segment
  3195.         mov     dx,offset serdum        ; offset of our interrupt routine
  3196.         push    ds                      ; save ds around next DOS call
  3197.         mov     bx,cs                   ; compose full address of our routine
  3198.         mov     ds,bx                   ; segment is the code segment
  3199.         mov     ah,25H                  ; set interrupt address from ds:dx
  3200.         int     dos
  3201.         pop     ds
  3202.         pop     es
  3203.         pop     bx
  3204.         mov     portin,1                ; Remember port has been initialized
  3205.         cli                             ; Disable interrupts
  3206.         cld                             ; Do increments in string operations
  3207.         mov     ax,modem.mdstat
  3208.         mov     mst,ax                  ; Use this address for status
  3209.         mov     ax,modem.mddat
  3210.         mov     mdat,ax                 ; Use this address for data.
  3211.         mov     al,modem.mdmeoi
  3212.         mov     mdeoi,al                ; Use to signify end-of-interrupt.
  3213.         in      al,21H                  ; Set up 8259 interrupt controller
  3214.         and     al,modem.mden   ; Enable INT3 or INT4. (bit=0 means enable)
  3215.         out     21H,al                  ; rewrite interrupt mask byte
  3216.         mov     dx,modem.mdcom  ; Set up the serial card Line Control Reg.
  3217.         in      al,dx                   ; get present settings
  3218.         mov     savlcr,al               ; save them for restoration
  3219.         mov     al,3                    ; 8 data bits. DLAB = 0
  3220.         out     dx,al
  3221.         mov     dx,modem.mddat     ; data and command port, read and flush any
  3222.         in      al,dx                   ; char in UART's receive buffer
  3223.         inc     dx                ; increment to interrupt enable register 3f9h
  3224.         mov     al,1                    ; Set up interrupt enable register
  3225.         out     dx,al                   ;  for Data Available only
  3226.         add     dx,3                ; increment to modem control register 3fch
  3227.         mov     al,0bh            ; assert DTR, RTS, not OUT1, and OUT2
  3228.         out     dx,al             ; OUT2 high turns on interrupt driver chip
  3229.         sti                       ; Allow interrupts (AFTER next instr)
  3230.         jmp     short serin4            ; finish up
  3231.  
  3232. serin3: cmp     flags.comflg,'N'        ; Network?
  3233.         jne     serin4                  ; ne = no
  3234.         call    setnet                  ; setup network session and pcnet flag
  3235.         jnc     serin4                  ; nc = success
  3236.         ret                             ; fail, carry set, leave portin at 0
  3237.  
  3238. serin4: push    bx
  3239.         mov     bx,portval              ; get port data structure
  3240.         mov     parmsk,0ffh             ; parity mask, assume parity is None
  3241.         cmp     [bx].parflg,parnon      ; is it None?
  3242.         je      serin1                  ; e = yes
  3243.         mov     parmsk,07fh             ; no, pass lower 7 bits as data
  3244. serin1: mov     bx,[bx].flowc           ; get flow control chars
  3245.         mov     flowoff,bl              ; xoff or null
  3246.         mov     flowon,bh               ; xon or null
  3247.         mov     xofrcv,off              ; clear xoff received flag
  3248.         pop     bx
  3249.         mov     portin,1                ; say initialized
  3250.         clc                             ; carry clear for success
  3251.         ret                             ; We're done
  3252. SERINI  ENDP
  3253.  
  3254. ; Reset the serial port.  This is the opposite of serini.  Calling
  3255. ; this twice without intervening calls to serini should be harmless.
  3256. ; Moved push/pop es code to do quicker exit before interrupts enabled. [jrd]
  3257. ; Returns normally.
  3258. ; 22 June 1986 Leave OUT1 low to avoid resetting Hayes 1200B's. [jrd]
  3259. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  3260. ; 17 May 1987 Redo for COM3/4 support [jrd]
  3261. SERRST  PROC    NEAR
  3262.         cmp     portin,0                ; Reset already?
  3263.         jg      srst3                   ; g = no
  3264.         ret                             ; e = yes, l=not used yet, just leave
  3265. srst3:  test    clone,0ffh              ; running on a non-compatible UART?
  3266.         jz      srst4                   ; z = no, real UART
  3267.         jmp     srst1                   ; nz = yes (Bios or Net)
  3268. srst4:  push    word ptr savsci         ; save original interrupt owner
  3269.         push    word ptr savsci+2       ; offset and segment
  3270.         mov     word ptr savsci,offset nulint ; redirect to our null routine
  3271.         mov     ax,cs                   ; segment of null routine is code
  3272.         mov     word ptr savsci+2,ax
  3273.         mov     cx,0                    ; loop counter
  3274. srst2:  mov     dx,modem.mdstat         ; status register
  3275.         in      al,dx
  3276.         jmp     $+2                     ; chip access delay
  3277.         test    al,40h                  ; both xmtr output registers empty?
  3278.         loopz   srst2                   ; z = no, wait for them a while
  3279.         mov     dx,modem.mddat          ; modem base address 3f8h
  3280.         add     dx,1                    ; point at int enable reg 3f9h
  3281.         mov     al,0
  3282.         out     dx,al                   ; disable interrupts from this source
  3283.         jmp     $+2                     ; let stray interrupts occur now
  3284.         jmp     $+2
  3285.         add     dx,2                    ; point at Line Control Register 3fbh
  3286.         mov     al,savlcr               ; saved bit pattern
  3287.         and     al,not 80h              ; force DLAB bit to 0
  3288.         out     dx,al                   ; restore line control state
  3289.                 ; clear modem's delta status bits and reassert DTR etc
  3290.         inc     dx              ; increment to modem control register 3fch
  3291.         mov     al,03h          ; reassert DTR,RTS,but not OUT1 and not OUT2
  3292.         out     dx,al           ;  OUT2 low to turn off interrupt drivers
  3293.         jmp     $+2             ; pause, in case stray interrupt is generated
  3294.         jmp     $+2             ; which is more than likely, hence nulint.
  3295.         add     dx,2                    ; modem status register 3feh
  3296.         in      al,dx                   ; clear status register by reading it
  3297.         jmp     $+2
  3298.         mov     mdmhand,al              ; save here for Show Modem
  3299.         cli                             ; Disable interrupts
  3300.         in      al,21H                  ; Interrupt controller
  3301.         or      al,modem.mddis          ; Inhibit IRQ 3 or IRQ 4
  3302.         pop     word ptr savsci+2       ; recover original int owner's addr
  3303.         pop     word ptr savsci
  3304.         sti                             ; replace original IRQ intrpt vector
  3305.         push    bx
  3306.         mov     al,byte ptr modem.mdintv ; vector number to do
  3307.         mov     dx,word ptr savsci      ; offset part
  3308.         push    ds
  3309.         mov     bx,word ptr savsci+2    ; segment part
  3310.         mov     ds,bx                   ; ds:dx has interrupt vector
  3311.         mov     ah,25H                  ; set interrupt vector
  3312.         int     dos                     ; replaced
  3313.         pop     ds
  3314.         mov     al,rs232        ; Bios serial port interrupt vector to restore
  3315.         mov     dx,word ptr sav232      ; offset part
  3316.         push    ds
  3317.         mov     bx,word ptr sav232+2    ; segment part
  3318.         mov     ds,bx
  3319.         mov     ah,25h                  ; set interrupt vector
  3320.         int     dos
  3321.         pop     ds
  3322.         pop     bx
  3323.         cli
  3324.         mov     ah,savirq               ; saved Interrupt state
  3325.         and     ah,modem.mddis          ; pick out our IRQ bit
  3326.         in      al,21h                  ; get current intrpt controller state
  3327.         jmp     $+2
  3328.         xor     al,modem.mddis          ; remove our IRQ bit
  3329.         or      al,ah                   ; set previous state
  3330.         out     21h,al                  ; reset IRQ 3 or 4 to original state
  3331.         sti
  3332.                                         ; non-UART processes
  3333. srst1:  cmp     pcnet,0                 ; a network active?
  3334.         je      srst9                   ; e = no
  3335.         cmp     flags.comflg,'N'        ; NetBios network?
  3336.         jne     srst9                   ; ne = no
  3337.         cmp     rposted,0               ; receive outstanding?
  3338.         je      srst9                   ; e = no
  3339.         mov     can.scb_baddr,offset rcv ; cancel receives
  3340.         push    bx
  3341.         mov     bx,offset can
  3342.         call    session
  3343.         pop     bx
  3344.         mov     ax,1
  3345.         call    pcwait                  ; wait one millisec
  3346.         cmp     rcv.scb_err,0           ; success?
  3347.         jne     srst9                   ; ne = no, leave interlock set
  3348.         mov     rposted,0               ; say no receives posted
  3349. srst9:  mov     portin,0                ; Reset flag
  3350.         ret                             ; All done
  3351. SERRST  ENDP
  3352.  
  3353. ; Null interrupt routine, to handle strays
  3354. nulint  proc    near
  3355.         push ax
  3356.         push dx
  3357.         mov al,20h                      ; general EOI
  3358.         mov dx,intcon1                  ; to 8259 interrupt controller
  3359.         out dx,al                       ; clear controller chip
  3360.         pop dx
  3361.         pop ax
  3362.         iret
  3363. nulint  endp
  3364.  
  3365. ; Dummy Interrupt 14H to defeat DOS interference with serial port when CTTY
  3366. ; and Kermit use the port simultaneously. If ports differ then chain DOS to
  3367. ; original Int 14H Bios code. Else return dummy status=ok reports and
  3368. ; Backspace for Read, ignore char for Write.
  3369. ; Entered with AH = function request, AL = char to be sent, DX = com port num
  3370. ; CS is our code segment, DS is DOS's, SS is ours or DOS's, interrupts off.
  3371. ; 25 June 1987 [jrd]
  3372. SERDUM  PROC    FAR
  3373.         push    ds                      ; preserve all registers
  3374.         push    ax
  3375.         mov     ax,seg datas            ; get our data segment
  3376.         mov     ds,ax
  3377.         mov     al,flags.comflg         ; get port id (COM1 = 1, COM2 = 2)
  3378.         and     al,7                    ; use lower three bits
  3379.         dec     al                      ; DOS counts COM1 as 0, etc
  3380.         cmp     dl,al           ; referencing same port as Kermit is using?
  3381.         pop     ax                      ; recover request parameters
  3382.         jne     serdu1                  ; ne = no, chain to Bios routine
  3383.         pop     ds
  3384.         cmp     ah,0                    ; initialization request?
  3385.         je      serdu3                  ; e = yes, return dummy status=ok rpt
  3386.         cmp     ah,1                    ; send char in al?
  3387.         jne     serdu2                  ; ne = no
  3388.         mov     ah,60h                  ; yes, set line status=ok in ah
  3389.         iret
  3390. serdu2: cmp     ah,2                    ; receive char (and wait for it)?
  3391.         jne     serdu3                  ; ne = no, return dummy report
  3392.         mov     al,bs                   ; yes, return ascii BS to DOS
  3393.         mov     ah,0                    ; ah = errors (none here)
  3394.         iret
  3395. serdu3: mov     ax,60b0h                ; dummy status report:xmtr empty, CD,
  3396.         iret                            ;  DSR, and CTS are on
  3397.  
  3398. serdu1: pop     tempdum                 ; save old ds
  3399.         push    word ptr sav232+2       ; push Bios int 14H handler segment
  3400.         push    word ptr sav232         ; push Bios int 14H handler offset
  3401.         push    tempdum                 ; recover old ds
  3402.         pop     ds
  3403.         ret                             ; do a ret far (chain to Bios)
  3404. SERDUM  ENDP
  3405.  
  3406. ; Serial port interrupt routine.  This is not accessible outside this
  3407. ; module, handles serial port receiver interrupts.
  3408. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's.
  3409. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  3410. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  3411. ; done modulo size of Source. All pointer management is handled here.
  3412. ; Control-G char substituted for char(s) lost in overrun condition.
  3413. ; Upgraded to read cause of interrupt from interrupt ident reg (accepts only
  3414. ;  data ready), chain to old interrupt if source is not our device.
  3415. ; 9 Feb 1988 Add storage of interrupt cause in intkind. [jrd]
  3416.  
  3417. SERINT  PROC  FAR
  3418.         push    ax                      ; save registers
  3419.         push    dx                      ;
  3420.         push    ds
  3421.         mov     ax,seg datas
  3422.         mov     ds,ax                   ; address data segment
  3423.         mov     dx,mdat                 ; modem base address
  3424.         add     dx,2            ; increment to Interrupt Identification Reg
  3425.         in      al,dx                   ; get interrupt cause
  3426.         mov     intkind,al              ; save cause here
  3427.         test    al,1            ; interrupt available if this bit is zero
  3428.         jz      srintc                  ; z = interrupt is from our source
  3429.         pop     tempsci                 ;  save old ds
  3430.         pop     dx              ;  clean the stack and prepare for ret far
  3431.         pop     ax              ;  to old int handler (same as a jump there)
  3432.         push    word ptr savsci+2       ; old handler segment
  3433.         push    word ptr savsci         ; old handler offset
  3434.         push    tempsci                 ; recover old ds
  3435.         pop     ds
  3436.         ret                             ; do far return (chain to old handler)
  3437. srintc: mov     al,mdeoi                ; allow interrupt controller to run
  3438.         out     intcon1,al              ; Send End-of-Interrupt to 8259
  3439.         test    intkind,4               ; data ready?
  3440.         jnz     srint0a                 ; nz = yes, else ignore
  3441. srint0: sti                             ; else turn on interrupts
  3442.         jmp     retint                  ;  and exit now (common jump point)
  3443.  
  3444. srint0a:mov     dx,mst                  ; Asynch status port
  3445.         in      al,dx
  3446.         and     al,mdmover              ; select overrun bit
  3447.         mov     ah,al                   ; save it for later
  3448.         mov     dx,mdat
  3449.         in      al,dx                   ; read the received character into al
  3450.         mov     dh,al              ; dh = working copy. Check null, flow cntl
  3451.         and     dh,parmsk               ; strip parity temporarily, if any
  3452. ;;;;;   jz      srint0                  ; if null ignore char
  3453. srint0b:cmp     flowoff,0               ; flow control active?
  3454.         je      srint2                  ; e = no
  3455.         cmp     dh,flowoff              ; acting on Xoff?
  3456.         jne     srint1                  ; ne = Nope, go on
  3457.         cmp     xofsnt,0                ; have we sent an outstanding XOFF?
  3458.         jne     srint0                  ; ne = yes, ignore (possible echo)
  3459.         mov     xofrcv,bufon            ; Set the flag saying XOFF received
  3460.         jmp     srint0                  ;  and exit
  3461. srint1: cmp     dh,flowon               ; acting on Xon?
  3462.         jne     srint2                  ; ne = no, go on
  3463.         mov     xofrcv,off              ; Clear the XOFF received flag
  3464.         jmp     srint0                  ;  and exit
  3465. srint2: push    bx                      ; save register
  3466.         or      ah,ah                   ; overrun?
  3467.         jz      srint2a                 ; z = no
  3468.         mov     ah,al                   ; yes, save present char
  3469.         mov     al,bell                 ; insert control-G for missing char
  3470. srint2a:mov     bx,srcpnt               ; address of buffer storage slot
  3471.         mov     byte ptr [bx],al       ; store the new char in buffer "source"
  3472.         inc     srcpnt                  ; point to next slot
  3473.         inc     bx
  3474.         cmp     bx,offset source + bufsiz ; beyond end of buffer?
  3475.         jb      srint3                  ; b = not past end
  3476.         mov     srcpnt,offset source    ; wrap buffer around
  3477. srint3: cmp     count,bufsiz            ; filled already?
  3478.         jae     srint4                  ; ae = yes
  3479.         inc     count                   ; no, add a char
  3480. srint4: or      ah,ah                   ; anything in overrun storage?
  3481.         jz      srint4a                 ; z = no
  3482.         mov     al,ah                   ; recover any recent char from overrun
  3483.         xor     ah,ah                   ; clear overrun storage
  3484.         jmp     srint2a                 ; yes, go store real second char
  3485. srint4a:pop     bx                      ; restore reg
  3486.         sti                          ; ok to allow interrupts now, not before
  3487.         cmp     count,mntrgh            ; past the high trigger point?
  3488.         jbe     retint                  ; be = no, we're within our limit
  3489.         test    xofsnt,bufon        ; Has an XOFF been sent by buffer control?
  3490.         jnz     retint                  ; nz = Yes
  3491.         mov     al,flowoff              ; get the flow off char (Xoff or null)
  3492.         or      al,al                   ; don't send nul chars
  3493.         jz      retint                  ; z = null, nothing to send
  3494.         call    dopar                   ; Set parity appropriately
  3495.         mov     ah,al                  ; Don't overwrite character with status
  3496.         push    cx                      ; save reg
  3497.         xor     cx,cx                   ; loop counter
  3498. srint5: mov     dx,modem.mdstat         ; Get port status
  3499.         in      al,dx
  3500.         test    al,20H                  ; Transmitter ready?
  3501.         jnz     srint6                  ; nz = yes
  3502.         jmp     $+2                     ; use time, prevent overdriving UART
  3503.         loop    srint5                  ; else wait loop, cx times
  3504.          jmp    srint7                  ; Timeout
  3505. srint6: mov     al,ah                   ; Now send out the flow control char
  3506.         mov     dx,modem.mddat
  3507.         jmp     $+2
  3508.         out     dx,al
  3509.         mov     xofsnt,bufon       ; Remember we sent an XOFF at buffer level
  3510. srint7: pop     cx                      ; restore reg
  3511. retint: pop     ds
  3512.         pop     dx
  3513.         pop     ax
  3514.         iret
  3515. SERINT  ENDP
  3516.  
  3517. DTRLOW  PROC    NEAR            ; Global proc to Hangup the Phone or Network
  3518.                                 ; by making DTR and RTS low (phone). [jrd]
  3519.         mov     ah,cmtxt        ; allow text, to be able to display help
  3520.         mov     bx,offset rdbuf         ; dummy buffer
  3521.         mov     dx,offset hnghlp        ; help message
  3522.         call    comnd                   ; get a confirm
  3523.          jmp    r
  3524.          nop
  3525.         cmp     clone,'0'               ; running on a semi-clone?
  3526.         jb      dtrlow2                 ; b = no
  3527.         cmp     clone,'4'
  3528.         jb      dtrlow1                 ; b = yes, can't access modem lines
  3529. dtrlow2:call    serhng                  ; drop DTR and RTS
  3530.         cmp     taklev,0                ; in a Take file or macro?
  3531.         jne     dtrlow1                 ; ne = yes, no message
  3532.         mov     ah,prstr                ; give a nice message
  3533.         mov     dx,offset hngmsg
  3534.         int     dos
  3535. dtrlow1:jmp     rskp
  3536. DTRLOW  ENDP
  3537.  
  3538. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  3539. ; to terminate the connection. 29 March 1986 [jrd]
  3540. ; 5 April 1987 Add 500 millisec wait with lines low before returning. [jrd]
  3541. ; Calling this twice without intervening calls to serini should be harmless.
  3542. ; If network then call nethangup procedure to hangup the session without
  3543. ; losing local name information.
  3544. ; Returns normally.
  3545.  
  3546. serhng  proc    near    ; clear modem's delta status bits and lower DTR & RTS
  3547.         cmp     clone,'U'               ; Ungermann Bass network?
  3548.         je      shng2                   ; e = yes
  3549.         cmp     clone,'N'               ; network?
  3550.         jne     shng1                   ; ne = no
  3551. shng2:  cmp     pcnet,0                 ; network operational?
  3552.         je      shng1                   ; e = no
  3553.         call    nethangup               ; break the session
  3554.         call    serrst                  ; reset port so can be opened again
  3555.         ret
  3556. shng1:  call    serrst                  ; reset port so serini can set DTR
  3557.         cli                             ; Disable interrupts
  3558.         push    ax
  3559.         push    dx
  3560.         mov     dx,modem.mddat          ; serial port base address
  3561.         add     dx,4                    ; increment to control register
  3562.         mov     al,08h                 ; reassert OUT2, un-assert DTR,RTS,OUT1
  3563.         out     dx,al
  3564.         jmp     $+2
  3565.         add     dx,2                    ; increment to modem status register
  3566.         in      al,dx                   ; Clear Status reg by reading it
  3567. shngx:  sti                             ; Enable interrupts
  3568.         mov     ax,500                  ; 500 millisec, for pcwait
  3569.         call    pcwait              ; keep lines low for at least 500 millisec
  3570.         pop     dx
  3571.         pop     ax
  3572.         clc
  3573.         ret
  3574. serhng  endp
  3575.  
  3576. ; Jumping to this location is like retskp.  It assumes the instruction
  3577. ;   after the call is a jmp addr.
  3578.  
  3579. RSKP    PROC    NEAR
  3580.         pop     bp
  3581.         add     bp,3
  3582.         push    bp
  3583.         ret
  3584. RSKP    ENDP
  3585.  
  3586. ; Jumping here is the same as a ret
  3587.  
  3588. R       PROC    NEAR
  3589.         ret
  3590. R       ENDP
  3591.  
  3592. code    ends
  3593.         end
  3594.  
  3595.  
  3596.